Avoid unnecessary setState call when Route receives same props.
See original GitHub issueI just encounter a situation. I have the below App component connected to Redux. The requestQuantity changes according to current processing XHRs , which causes the App re-render.
Then the TopicList will re-render which shouldn’t happen. The TopicList is also connected to Redux and doesn’t depend on requestQuantity, based on the shallow comparison of Redux’s connect, changing of requestQuantity has nothing to do with the TopicList’s render.
class App extends Component {
render() {
const { requestQuantity } = this.props;
return (
<div>
<Router>
<Switch>
<Route exact path="/" component={TopicList} />
<Route path="/login" component={Login} />
<Route path="/topics" component={TopicList} />
</Switch>
</Router>
{requestQuantity > 0 && <Loading />}
</div>
);
}
}
const mapStateToProps = (state, props) => {
return {
requestQuantity: getRequestQuantity(state)
};
};
export default connect(mapStateToProps)(App);
I check the source code and find the Route’s componentWillReceiveProps will always call the setState, which set a new match object. It is the new match prop passed to the TopicList causing the Redux’s shallow comparison failed.
I think we can make some comparison before calling the setState. If the location, strict, exact and sensitive don’t change, we can skip the setState and just passing the old state to
the components in Route. In this way , the components can render more efficiently especially when using with Redux and Mobx.
componentWillReceiveProps(nextProps, nextContext) {
warning(
!(nextProps.location && !this.props.location),
'<Route> elements should not change from uncontrolled to controlled (or vice versa). You initially used no "location" prop and then provided one on a subsequent render.'
)
warning(
!(!nextProps.location && this.props.location),
'<Route> elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.'
)
// do some shouldComputeMatch logic before setState
this.setState({
match: this.computeMatch(nextProps, nextContext.router)
})
}
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (3 by maintainers)

Top Related StackOverflow Question
@johnnyreilly aha, you’re right, the workaround is by me.
There’s a workaround here: https://stackoverflow.com/questions/47375973/react-router-causes-redux-container-components-re-render-unneccessary (perhaps by original poster?)
It would be great to know if this is considered “safe”: