Performances: quick solution "withRouter" VS render a pathless <Route>.
See original GitHub issueHere (https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md) it says:
Quick Solution
If you are running into this issue while using a higher-order component like connect (from react-redux) or observer (from Mobx), you can just wrap that component in a withRouter to remove the blocked updates.
// redux before
const MyConnectedComponent = connect(mapStateToProps)(MyComponent)
// redux afterconst MyConnectedComponent = withRouter(connect(mapStateToProps)(MyComponent))
This is not the most efficient solution, but will prevent the blocked updates issue. For more info regarding this solution, read the Redux guide. To understand why this is not the most optimal solution, read this thread.
So this is not optimal for performances and then it continues:
Recommended Solution
The key to avoiding blocked re-renders after location changes is to pass the blocking component the location object as a prop. This will be different whenever the location changes, so comparisons will detect that the current and next location are different.
What happens when the component isn’t being rendered by a <Route> and the component rendering it does not have the location in its variable scope? There are two approaches that you can take to automatically inject the location as a prop of your component.
What happens when the component isn’t being rendered by a <Route> and the component rendering it does not have the location in its variable scope? There are two approaches that you can take to automatically inject the location as a prop of your component.
Render a pathless <Route>. While <Route>s are typically used for matching a specific path, a pathless <Route> will always match, so it will always render its component. // pathless <Route> = <Blocker> will always be rendered
const MyComponent= () => ( <SomeComponent> <Route component={Blocker} /> </SomeComponent> )
So I don’t understand: the second one is better than the first one?
Using this: <Route component={Blocker} />
is better (for performances) than this: withRouter(connect(mapStateToProps)(MyComponent))
?
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (2 by maintainers)
@johnunclesam Using
withRouter
literally renders a pathless<Route>
. If your only use forwithRouter
is to prevent blocked updates and you already have access to thelocation
prop, then you are just adding extra components to your application by usingwithRouter
instead of passing thelocation
as a prop. If you don’t have access to thelocation
, then just usewithRouter
.For example, let’s imagine we have the following components:
The
<Thing>
component is rendered by a<Route>
, which means that it is passed thelocation
prop when it is rendered. Our<ConnectedOne>
and<ConnectedTwo>
components are wrapped inconnect
, which prevents them from re-rendering by default. However, our<Thing>
can pass them thelocation
prop, which will cause theshouldComponentUpdate
method of the component returned byconnect
to returntrue
.Alternatively, we could just wrap
ConnectedOne
andConnectedTwo
inwithRouter
to get the same result.What is the difference? Well, let’s take a look at the element trees that each approach will create:
Both of the above component trees have the same end result, but the latter adds extra components to your application. Is using
withRouter
going to have a huge performance hit on your application? Probably not unless you’re wrapping half of your components inwithRouter
. Still, if you already have access to thelocation
component, you might as well just use the prop. The worst is when there is a component that is already rendered by a<Route>
and gets wrapped inwithRouter
.Thanks @pshrmn. Much appreciated.