0

With class based components I could pass on the state to components that are rendered by props by saying:

<Route path='/someroute' component={SomeComponent} someprop={someprop} />

However, now I am using react hooks and I have my state defined as:

const [myProjects, setMyProjects] = useState([
     {projectName: Some project, id: 1},
     {projectName: Some project, id: 2},
]);

Now the route is ignoring this prop. I did read something about people using something like render instead of component. But the effort and amount of code this takes looks too hacky or much to me? I mean hooks were introduced for better code. And now a simple 'someprop={someprop}' has to be replaced by a codeblock?

I also read something about router v5 having some new stuff, but I couldn't find a reliable and clean way to pass on props.

Can someone educate me a bit on this matter?

Thank you in advance for the time!

Update with answer

If you're here after googling, here is a sandbox with the solution! This is based on the selected solution/answer. Other viewers may view this as well to see the problem I was facing. Maybe someone has additional information. I am still learning React, and gosh is this a big learning curve for me haha

https://codesandbox.io/s/admiring-diffie-9kfgx?file=/src/App.js

Pgreat
  • 45
  • 8

2 Answers2

3

This has nothing to do with hooks or not, it's based on how React Router Dom works.

If don't you need the match, location, or history props, then you can simplify your component;

<Route path='/someroute'>
   <SomeComponent someprop={someprop}/>
</Route>

If you do need those, then you can use one of React Router's hooks in your child component to get them, you can use the render prop of the route. You definitely don't want to try this with the component prop as that will create a new component in every render.

<Route path='/someroute' render={routeProps=><SomeComponent {...routeProps} someprop={someprop}/>}  />

Another route to do this is using the withRouter Higher order component:

//outside of the parent component
const SomeComponentWithRouter = withRouter(SomeComponent);

//In the render function:

<Route path='/someroute'>
   <SomeComponentWithRouter someprop={someprop}/>
</Route>

Edit for posters questions:

  1. The render tag you showed, does it cause unnecessary re-renders? I read something about that.

The render prop doesn't cause unnecessary re-renders as far as I'm aware. What you might be thinking of is that trying the same as the render prop with the component prop causes issues:

From React Router's documentation:

When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).

https://tylermcginnis.com/react-router-pass-props-to-components/

Reactjs - `component` vs `render` in Route

  1. And I must ask, could you post some beginner-friendly reference about the 'withRouter' you were talking about?

Again, I must refer you to React Router's documentation. It is one of the best sources of information about React Router and is kept up to date.

The main gist of withRouter is that it's a higher order component and will basically give you a new version of your component that always has the match, history, and location props passed in (match is based on the first matched Route up the component hierarchy).

There's not really much else to say about withRouter, I have an example of how to use it, and it adds those 3 props to your component.

I'd personally recommend using the hooks that React Router provide if you are working with function components as they don't require higher order components. Like any other hooks, they can be more easily composed with any custom hook or function component.

https://css-tricks.com/the-hooks-of-react-router/

Zachary Haber
  • 7,380
  • 1
  • 6
  • 19
  • Thank you! Using the way worked wonders! Exactly what I needed and google lacked to provide haha! Two questions! The render tag you showed, does it cause unnecessary re-renders? I read something about that. Could you enlighten me about this? And I must ask, could you post some beginner-friendly reference about the 'withRouter' you were talking about? Looks very interesting! I thank you for your info, answer and overal help! Realy appreciated! – Pgreat May 02 '20 at 00:14
  • I've answered the question you've asked, hopefully this helps. I've also added a bunch of links to different documentation and resources for you to take a look at. – Zachary Haber May 02 '20 at 00:39
0

Have you tried this?

<Route path="/someroute" render={(props) => <SomeComponent {...props} someprop={someprop} />} />

  • This is exactly what I've read. But I have also read that doing this forces a re-render. And I don't think its good practice to re-render unnecessarily? And as I said. Compare what you typed to simply saying: state={state}. Hooks should make things easier/more readable yes? or am I missing something in your opinion? (im pretty new to this so sorry if I don't understand some things :P ) – Pgreat May 02 '20 at 00:04
  • @Pgreat take a look at the official [documentation](https://reacttraining.com/react-router/web/api/Route/render-func), with this approach the component should not create again with every render – Mauricio Avendaño May 02 '20 at 00:27
  • Ah ok! Good to hear, I shall :) – Pgreat May 02 '20 at 00:29