Improve docs when using dynamic routes under Route component
See original GitHub issueI could be misunderstanding some interaction here, but if what I’ve observed is true, then I’ve encountered a pitfall which I believe needs to be documented more.
In the project I work on I have effective this:
<Router history={history}>
<Switch>
<Route name="foo" path={`/foo`} component={FooComponent} />
<Route component={({ match }) => <BarComponent />} />
</Switch>
</Router>
The BarComponent contains a list of Routes which are code split (which shouldn’t matter for this)
<div>
<Header />
<Sidebar />
<Container>
<Switch>
<Route name="a1" path={`/a1`} component={({ match }) => <AuthenticationWrapper componentName="A1" match={match} />} />
<Route name="a2" path={`/a2`} component={({ match }) => <AuthenticationWrapper componentName="A2" match={match} />} />
</Switch>
</Container>
</div>
And now here is the problem. Within A2 there are tabs in that component, I handle the tables by a declarative route:
<Route path={`/a2/:tab`} children={({match, ...rest}) => {
Long story short, whenever I clicked a tab, which contained a react-router-dom Link, I noticed every single component under the dynamic route (and in reality probably the top level Route) was being re-mounted (componentDidMount being called).
So after digging into the react-router docs I saw that when defining a Route with component, which I do at the top level:
When you use component (instead of render, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function, you are creating a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. For inline rendering, use the render prop (below).
What I did then, at the top level is instead of using component with the a2 component, I switched it to render and now no more re-mounts. I’m still not entirely clear that this is the right approach.
If this really is the right approach, and RRv4 is meant to be used with dynamic routing, then shouldn’t the docs be very explicit in the children and render Route section and also in the example? From an outside perspective, it took a lot of searching in the issues section + docs + trial and error to finally realize that maybe I shouldn’t be using component at the top level. Nearly every example out there uses component instead of render at the top level, so it makes it a bit confusing. It looks like: https://reacttraining.com/react-router/web/example/animated-transitions uses render at the top level, while using dynamic routing below, which makes sense now, but there is no explanation of that in the example itself, or why it was used that way.
Apologies for being long winded, I hope that by logging this issue I can also save some other people time when dealing with this issue as well. Having the entire sub-tree re-mounted on each route change, due to dynamic routes, is a performance killer.
So maybe, correct me if I’m wrong, what I’m looking for is confirmation and addition to the docs to the effect of: “If a top level Route ultimately contains dynamic Routes under it, then that top level Route should use render instead of component otherwise all children will be re-mounted when the url changes”.
Issue Analytics
- State:
- Created 6 years ago
- Comments:13 (5 by maintainers)

Top Related StackOverflow Question
It’s not so much that it’s supported, but more that it’s possible, so folks will do it. And there’s nothing invalid about that pattern, it’s just weird.
It will also commonly happen if they have some sort of async loading component, which will change the component once it loads. That would be where I’d see this more likely to happen.
Let me make one correction to the above, it appears that by simply avoiding the
() => ...anonymous function within<Route component />that the re-mounting is avoided. I think my request above then is still valid, this should be clarified, especially when using dynamic routing as it can cause a lot of re-renders.