ServerBloke
ServerBloke

Reputation: 852

React router v6 access route params and pass as props

In react router v6, how can I pass route params to a component without the need to use useParams() in the component?

This is what I want to do:

<Route
  path='/'
  element={ProfileComponent username={'thedefault'}
/>
<Route
  exact
  path='/u/:username/'
  render={(props) => 
    <ProfileComponent username={props.match.params.username}/>
  }
/>

I don't want to put useParams() in the component because this tightly couples it to the URL. For example, what if I wanted to render another ProfileComponent elsewhere, with a different username to that in the URL. It seems to violate best practice for unit testing unless I can do it like my example.

Upvotes: 10

Views: 17841

Answers (2)

Drew Reese
Drew Reese

Reputation: 202836

I don't want to put useParams() in the component because this tightly couples it to the URL. For example, what if I wanted to render another ProfileComponent elsewhere, with a different username to that in the URL. It seems to violate best practice for unit testing unless I can do it like my example.

Any route using a username route match param would still be accessible via the useParams hook, but I think I understand what you are after. If I understand your question correctly you are asking how to map a route match param to a component prop in a generic way.

For this you can simply use a wrapper component to "sip" the route match param and pass it along to your component on any specific prop.

const ProfileComponentWrapper = () => {
  const { username } = useParams();
  return <ProfileComponent username={username} />;
};

...

<Route
  path='/u/:username/'
  element={<ProfileComponentWrapper />}
/>

Upvotes: 13

eneski
eneski

Reputation: 1655

In the docs, it is clearly specified that it is not possible

Normally in React you'd pass this as a prop: , but you don't control that information because it comes from the URL.

https://reactrouter.com/docs/en/v6/getting-started/tutorial#reading-url-params

So, you have to use useParams in the component

Upvotes: 2

Related Questions