How to pass params into link using React router v6?

Issue(s)

  1. react-router-dom v6 Route components rendered via the element prop don't receive route props.
  2. Route children components must use react hooks to access the route context, i.e. useParams, useLocation, useNavigate, etc... and therefore must be function components.
  3. 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.

  1. Convert DetailsPage to be a function component and use the useParams react hook.
  2. 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:

  1. Add the following line of code at the beginning of your class:

     import { useParams } from 'react-router-dom';
    
  2. 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}/>
        }
      }
    
  3. Next, change your class definition to this:

     class DetailsPage extends React.Component {
    
  4. Add the following line of code at the end of your class:

     export default withRouter(DetailsPage);