This is my main section class where all routes to the links is kept
export default class Section extends React.Component {
render() {
return (
<div style={{backgroundColor:"white"}}>
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/discover" element={<Discover/>} />
<Route path="/shop/makeup" element={<Makeup/>} />
<Route path="/home/:id" element={<DetailsPage/>} />
</Routes>
</div>
)}}
This is my card page which is getting data from the context.
import React from 'react';
import {DataContext} from './CardData.js';
import {Link} from 'react-router-dom'
import '../App.css';
export default class HomeCard extends React.Component {
static contextType = DataContext;
render(){
const {products} = this.context;
return (
<div>
<div className="card">
{ products.map((val,index)=>{
return(
<div className="card" key={val.id}>
<Card style={{ width: '14rem' }} className="cardhead">
<Card.Img variant="top" src={val.imgsrc} className="cardimg"/>
<Card.Body>
<Card.Text>{val.mname}
</Card.Text>
<Card
From here i had passed the val.id to the url of the page using LINK
<Link to={`/home/${val.id}`}>
<Button className="overlay" variant="primary">
{/* <a style={{color:"white"}} href={props.link} className="card-link">View</a> */}
View</Button> </Link>
<Card.Text><strong>{val.price}</strong>
</Card.Text>
<Card.Text><strong>{val.id}</strong>
</Card.Text>
</Card.Footer>
</Card.Body>
</Card>
</div>);
</div>
)}}
I want to access the the link url into the details page of my product which is as follows :
export default class DetailsPage extends React.Component {
static contextType = DataContext;
state = {
product: []
}
getProduct = () =>{
if(this.props.match.params.id){
const res = this.context.products;
const data = res.filter(item =>{
return item.id === this.props.match.params.id
})
this.setState({product: data})
}};
componentDidMount(){
this.getProduct();
}
render() {
const {product} = this.state;
const {addCart} = this.context;
return (
<>
{product.map(item =>(
<div className="details" key={item.id}>
<img src={item.imgsrc} alt=""/>
<div className="box">
<div className="row">
<h2>{item.mname}</h2>
<span>${item.price}</span>
</div>
<Link to="/cart" className="cart" onClick={() => addCart(item.id)}>
Add to cart
</Link>
</div> </div> ))} </> ) }}
Unfortunately it is giving an error saying TypeError: Cannot read property 'params' of undefined
Using react-router-dom v6import { useParams } from "react-router-dom"; const Something = (props) => { let { id } = useParams(); useEffect(() => { console. log(`/something/${id}`); },[]); // ..... } A quick and exact solution. Thanks for the details.
First you'll need to import the useSearchParams hook and destruct the return value to get the current value of, React Router v6 calls these the “search params” due to them existing on the window.
React Router v6 introduces an element property that replaces the render property/function. Thus passing URL parameters to class components is a little different but can still be done using a Wrapper function component.
Issue(s) react-router-dom v6 Routecomponents rendered via the elementprop don't receive route props. Route children components mustuse react hooks to access the route context, i.e. useParams, useLocation, useNavigate, etc... and therefore must be function components.
React Router v6 introduces a Routes component that replaces Switch. In order to use v6, you’ll need to convert all your <Switch> elements to <Routes>. React Router v6 introduces an element property that replaces the render property/function.
Function components can retrieve URL parameters using Hooks the usual way. Below is one common and easy way to create react routes. First, let’s wrap the root component with the BrowserRouter.
Route
components rendered via the element
prop don't receive route props.useParams
, useLocation
, useNavigate
, etc... and therefore must be function components.withRouter
Higher Order Component.DetailsPage
is a class-based component so I see a couple options for getting access to the route's match params.
DetailsPage
to be a function component and use the useParams
react hook.withRouter
HOC to access the route context and pass as props any of the react-hook accessible values.I won't cover converting a class-based component to a function component, but can provide a simple HOC solution to pass to DetailsPage
(or any other class-based component) the match params.
const withRouter = WrappedComponent => props => {
const params = useParams();
// etc... other react-router-dom v6 hooks
return (
<WrappedComponent
{...props}
params={params}
// etc...
/>
);
};
You can now wrap & export your class-based components in the very familiar way they were from v4/v5.
v6 api-reference
Pass props via Link component in React Router v6 by a separate prop called state
like <Link to="/" state={{ foo: bar }}>
.
Example:
<Link
to={`/login`}
state={{ from: "the-page-id" }}
>
Login to see this page
</Link>
And retrieve it using useLocation()
hook:
import { useLocation } from "react-router-dom";
...
const location = useLocation();
const { from } = location.state;
console.log(from); // output: "the-page-id"
This should be used with function components only not class components.
<Route path="/something/:id" element={<Something />} />
import { useParams } from "react-router-dom";
const Something = (props) => {
let { id } = useParams();
useEffect(() => {
console.log(`/something/${id}`);
},[]);
// .....
}
I had this same problem and scoured the internet for an easy solution. I didn't want to rewrite all my class components as functional components but I thought I might have to. However, I used a withRouter function with useParams() and it works really well and is easy to follow.
To solve your problem so you don't have to rewrite your DetailsPage class as a function, follow these steps:
Add the following line of code at the beginning of your class:
import { useParams } from 'react-router-dom';
Then add this function above your class (copy it exactly):
export function withRouter(Children){
return(props)=>{
const match = {params: useParams()};
return <Children {...props} match = {match}/>
}
}
Next, change your class definition to this:
class DetailsPage extends React.Component {
Add the following line of code at the end of your class:
export default withRouter(DetailsPage);
useNavigate
const navigate = useNavigate();
function _navigateToPage (pageNumber) {
const page = pageNumber
const title = "Hello World";
navigate("/fragment", {
state:{
page,
title
},
});
}
useLocation
const params = useLocation();
console.log(params);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With