How to pass button text content to another page in React? - reactjs

I'm not really into React but I have to do a simply appointment page.
I've built a simple calendar
(screenshot). Every "hour" button links to another page where I want to show the chosen time.
<div className="dzisiaj dzien" >
Dziś <br></br>
<button className="godzina niedostepny"><s>14:15</s></button>
<Link to="/Page3">
<button className="godzina">15:00</button>
</Link>
<button className="godzina">16:00</button>
<button className="godzina niedostepny"><s>16:45</s></button>
</div>
I've just used a Link component to redirect to a next page, but I have no idea how to display the specific chosen hour. I'd really appreciate some code example.
edit:
I feel like I've messed something up somewhere since it still doesn't work.
Console says:
"Uncaught TypeError: Cannot read properties of undefined (reading 'state')"
for line 7 and 12 of page3

The Link component attribute to can also be an object with additional parameters. See the full documentation here: https://v5.reactrouter.com/web/api/Link
This allows you to do the following:
<Link to={{ pathname: "/page3", state: { time: "15:00" } }} >{ /** ... */ }</Link>
On the target component, you can access the state via props.location.state as follows:
const Page3 = (props) => {
const { time } = props.location.state;
return (
<div id="page3">
<Header/>
<div id="test">
<p>{ time }</p>
</div>
</div>
)
}

Related

How to solve react hydration error in Nextjs

I have created small nextjs page using wordpress REST API, Now react-hydration-error error show this page.I am using react html parser npm. How do I solve this error. could you please solve this error.
my code:
import Image from 'next/image'
import React ,{Component}from 'react'
import Link from 'next/link';
import { BiCalendar } from "react-icons/bi";
import ReactHtmlParser from 'react-html-parser';
export default class Blog extends Component{
constructor(props){
super(props);
this.state={
data: props.bloglist,
isLoading: true,
dataLoaded: false,
};
}
render(){
if (!this.state.data) {
return null;
}
console.log(this.state.data)
return(
<>
<div className="container blog-section">
<div className='row'>
<h2>Latest Posts</h2>
</div>
<div className='row'>
{
this.state.data.map(((x,i) =>(
<div className='col-md-4 boxs text-center' key={i}>
<div className='bg-info'>
<img src={x.images.large} className='img-fluid'/>
<h3>{x.title.rendered} </h3>
<p className='shopping'><span><BiCalendar/> {x.date}</span> </p>
{/* <p dangerouslySetInnerHTML={{__html: x.excerpt.rendered}}></p><span><BiShoppingBag/> {x.slug}</span> */}
<p class='expert'>{ReactHtmlParser(x.excerpt.rendered)}</p>
<Link href={"/blog"+"/"+x.slug+"/"+x.id } passHref={true}><p className='readmore'><span>Readmore </span></p></Link>
</div>
</div>
)))
}
</div>
</div>
</>
)
}
}
My original issues:
paragraph coming this format <p>If you have heard that there are ways to make money while shopping in the UAE and would lik</p> from API, So I converted to html.
I had this error, in my case I had <p> tag nested inside another <p> tag,
I was using Typography (MUI v5) to render text, switching to <Box> from <Typography> fixed the error.
We use components to build the React-based websites, These components are made using HTML tags. It is very important not to nest the same HTML elements.
For Example:
function Logo() {
return (
<Link href="/">
<a>
<Image
src="/images/logo.svg"
width={100}
height={75}
/>
</a>
</Link>
);
}
export default Logo;
Above is the Logo Component which has already the <a></a> tag inside it.
In this example, you will get the React Hydration Error if the <a> tag is used inside another <a> tag.
<a href="#">
<Logo />
</a>
So do not include the same HTML tags, which are hidden inside the
components to avoid react hydration error.
In my case I am using NextJS and I had a dropdown with react-select, the default value was changing after a small calculation, that does not like to nextjs, this is my previous code:
<Select options={seasons}
onChange={() => setSeason(e.value)}
defaultValue={seasons.find((x) => x.value == season) ? seasons.find((x) => x.value == season) : seasons[0]}
/>
So, I changed that calculation to the useEffect and initialized the react-select dropdown only when that value was calculated,now this is my current code that works:
{defaultSeason && (<Select options={seasons}
onChange={() => setSeason(e.value)}
defaultValue={defaultSeason}
/>)}
So, basically check that the defaultValue or anything else does not change after the html is sent to the client part in NextJS.
Follow these: https://nextjs.org/docs/messages/react-hydration-error
Or try deleting <a> within <Link> maybe.
My first code was this:
const isUserLoggedIn = is_user_logged_in()
// is_user_logged_in() checks for cookie of user token and returns boolean
Got the error about hydration
Then changed code to this:
const [isUserLoggedIn, setIsUserLoggedIn] = useState(null)
useEffect(() => {
setIsUserLoggedIn(is_user_logged_in())
}, [])
Renders was like this:
{isUserLoggedIn ? (
<>
{/* After login */}
<Profile USER={USER}/>
</>
) : (
<>
{/* Before login */}
<SigninButtons/>
</>
)}
And error solved
You can also check this
https://nextjs.org/docs/messages/react-hydration-error
Just try restarting the server. npm run dev. It worked for me. I was using react-hot-toaster.
Also try to check if you have sth like this:
<p>
<div>
Hello
</div>
</p>
div cant be inside p tag

How to NOT render/ hide a React component when no prop is passed?

TLDR: Cannot figure out why component is still being rendered while no props are passed.
So I have been building a NextJS application, and I have this banner component that is shown on every page of my website. It has some header text, buttons and an image:
const Banner = (props) => {
return (
<div className={bannerStyles.wrapper}>
<div className={classnames(bannerStyles.banner, "wrap", "center")}>
<div className={bannerStyles.banner_left}>
<h1>{props.header}</h1>
<div className={bannerStyles.button_wrapper}>
<div className={bannerStyles.button}>
<Button>{props.button || null}</Button>
</div>
<div className={bannerStyles.button}>
<Button>{props.scnd_button || null}</Button>
</div>
</div>
</div>
<div className={bannerStyles.banner_right}>
<Image src={props.image} alt=""></Image>
</div>
</div>
</div>
);
};
Inside of this, as you can see I have two Button components (The MDEast thing is an arrow icon):
const Button = ({children}) => {
return (
<div className={buttonStyles.button}>
<Link href="/"><a>{children} <MdEast /></a></Link>
</div>
)
}
Now I want the option that if no prop is passed, that the Button component(s) do(es) not render/ is hidden from the page, so that it is optional per page. Yet the Button does still render, even though I am not passing any props on my About page. My about page:
const About = () => {
return (
<>
<Banner
header="Hello this is my code"
image={banner_placeholder}
/>
</>
)
}
PS. I am fairly new to React and NextJS, so this might be a beginner mistake, or I am not understanding the fundamentals well enough, but could someone point me in the right direction please?
To conditionally render the button you can use:
props.button && <Button>{props.button}</Button>
When props.button is falsy, then button will not get rendered.

How do I consume data from a component where I am passing data using Link of react-router in class Components?

I have a carousel of cards. And each card has some data which if I click on the button on the card. I want to render the details of that particular card in different components on a different page which is item-details.
How do I achieve this in class components? There is an id in the map can I send using that in the details page where I am trying to render the full details of the card.
{this.state.data.map((item, idx) => {
return (
<div key={`edth_${idx}`} className="col-12 col-sm-6 col-lg-4 item explore-item" data-groups={item.group}>
<div className="card">
<div className="image-over">
<img className="card-img-top" src={item.img} alt="" />
</div>
<div className="card-caption col-12 p-0">
<div className="card-body">
<a href="/item-details">
<h5 className="mb-0">{item.title}</h5>
</a>
<div className="card-bottom d-flex justify-content-between">
<span>{item.price}</span>
<span>{item.count}</span>
</div>
<Link to={{pathname: '/item-details',state: [{img:'item.img',count: 'item.count', title: 'item.title', price: 'item.price'}]}} className="btn btn-bordered-white btn-smaller mt-3"> <i className="icon-handbag mr-2" />Check it out</Link>
</div>
</div>
</div>
</div>
);
})}
</div>
I have added the Link from react router instead of, but I still don't know how to consume this in the component which will be in /item-details.
Found out that instead of useLocation, I can use with router in class components so...
Imported useRouter in the item-details page and consuming like this in the render():
render() {
const { location } = this.props;
return (
<div className="item-info">
{location && location.img && <div className="item-thumb text-center">
<img src={location.img} />
</div>}
);
By doing this, I am not getting any error. But the img is not showing.
React is generally used for a single paged application (i.e. you wouldn't be sending users to different URLS) unless you are using something like NEXT, React Router, etc. for handling different pages.
Instead of sending the user to another page, you would render a new component with the details sent as a prop.
But if you're asking how to send information from a component to another page, i would suggest you look into React Router, which is designed to do this.
I'm not sure if this is actually what you're asking though so please provide further details on what your project is made up of.
In my experience, the best way to handle this would be to set the URL query when the onClick() handler is run. The view would update & the details would be fetched as needed. That way if you your homepage is mysite.com you can get more details by visiting mysite.com/moreinfo.
To accomplish this, you can use react-router-dom history API:
import { useHistory } from "react-router-dom";
function myComponent() {
let history = useHistory();
function handleClick() {
history.push("/moreinfo");
}
return (
<button type="button" onClick={handleClick}>
View More Info
</button>
);
}

How to create a button that opens a new page with the option to return back to previous page [ReactJS

Right below the page you see a 'back to log' button. If someone clicks on that it will return to the left page. So in order to do so I thought using react router will do the job. But not sure how to fix that.Is there someone who can help me to point me to the right direction. Keep in mind that it will not open a new tab!
Link to working snippet to understand the bigger picture of my app. CodeSandBox snippet here
return (
<div>
{info.map((show: any) => {
console.log(show.show)
return (
<div key={show.show.id}>
<ReactMarkdown source={show.show.name}/>
{show.show.image && <img src={show.show.image.medium}/>}
{show.show.genres.map((showGenre: string, index: number) => {
return (
<div key={index}>
<ReactMarkdown source={showGenre}/>
</div>
)
})}
<div>
<Router>
<ul>
<li>
<Link to="/">See deta</Link>
</li>
</ul>
</Router>
</div>
</div>
)
})}
</div>
)
Check out this working example (I placed notes in each file):
https://codesandbox.io/s/modest-panini-hkzlv?file=/src/App.js
Overview:
there are several ways to do this
my suggestion is to use the history npm and create a history.js file
you will also need to use Router from react-router-dom
in your parent component, or in a Context provider, you can store your state
in the parent component, use react-router-dom Switch and Route to place routes
depending on implementation, conditionally render show route for async state update
in your search component, place all your Links using react-router-dom
on click Links should also update app's state of your specific selection
this selection gets passed to the show route/component
in the show component attach an on click that uses history.goBack and resets state
this might help you:
this.props.history.goBack();
it goes back to prev page

The Use of "Navigate(-1)" Fails to Return to Previous Location in Gatsby

I am trying to create a simple "Back" button in Gatsby that returns the the previous page and retains the scroll position. This already happens when using the browser back button, but I'm struggling to produce a custom one. I've read in the Reach Router docs that you can add -1 as an argument to the navigate function to return to previous locations, but It instead throws the number value into the url and gives me a 404. Can someone give me an idea of what I've done wrong? Or if anyone else has managed to make a functional back button for Gatsby projects?
Here is my code-
import React from 'react';
import { graphql, navigate } from 'gatsby'
import Img from "gatsby-image"
import "./design.scss"
const designTemplate = (props) => {
return (
<section className="design">
<div className="design__container">
<h2 className="design__title">
{props.data.design.title}
</h2>
<Img className="design__image" fluid={props.data.design.localImage.childImageSharp.fluid} />
<p className="design__summary">
{props.data.design.summary}
</p>
</div>
<button onClick={navigate(-1)}>Go Back</button>
</section>
);
}
The issue you're having here is just that you didn't define a callback function for your onClick handler.
Instead of this:
<button onClick={navigate(-1)}>Go Back</button>
…you want to do this:
<button onClick={() => { navigate(-1) }}>Go Back</button>
Your onClick must have a callback(arrow function) like this
onClick={()=>{navigate(-1)}}
not
navigate(-1)

Resources