How to pass params into link using React router v6?
Issue(s)
- react-router-dom v6
Route
components rendered via theelement
prop don't receive route props. - Route children components must use react hooks to access the route context, i.e.
useParams
,useLocation
,useNavigate
, etc... and therefore must be function components. - There no longer exists a
withRouter
Higher Order Component.
Solution
DetailsPage
is a class-based component so I see a couple options for getting access to the route's match params.
- Convert
DetailsPage
to be a function component and use theuseParams
react hook. - Write your own
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.
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);