I am writing a React (ES6, v16) (typescript) application with react-router v4. I am observing a very strange behavior. Here is my render code (very much simplified):
render() {
<Switch>
<Route
path="/foo/add"
render={ props => {
return (
<FormEntry title="add new" />
);
}}
/>
<Route
path="/foo/edit/:id"
render={ props => {
return (
<FormEntry title="edit item" />
);
}}
/>
</Switch>
}
And here is the FormEntry component (simplified):
class FormEntry extends React.Component< { title: string }, any > {
render() {
return (
<div>
{this.props.title}
</div>
);
}
componentDidMount() {
// code goes here
}
componentDidUpdate() {
// code goes here
}
}
Now when, inside the application, I click a link "/foo/add", the handler in the first "Route" component is fired (as expected) and the component "FormEntry" is mounted. The method componentDidMount is rightfully fired.
Now I click the link "foo/edit/1". The handler of the second Route is fired.
This time, inside the "FormEntry" component, the lifecycle method "componentDidMount" is not fired, the method "componentDidUpdate" is called. But this is cleary a different "instance" of the FormEntry which is being mounted. I was expecting the see of the lifecycle methods kicked off...
It looks like there is only one instance of "FormEntry" in my application. So why in the second case (when Route handler for url "foo/edit:id") this instance does not go through the all lifecycle methods??
Is it a breaking change in the v16 version of React? ( I have not observed this behavior in previous versions of react).
Your insight will be very much appreciated
<Switch>
check the JSX
of the previous matched route and compare it with the new JSX
of next route.
If it does match, it will use it and only update changed values without re-mounting components.
Otherwise it will create new react elements and instantiate new components.
Check here: https://github.com/ReactTraining/react-router/pull/4592
A turn around for this is to use key attributes like this:
render() {
<Switch>
<Route
path="/foo/add"
render={ props => {
return (
<FormEntry key="1" title="add new" />
);
}}
/>
<Route
path="/foo/edit/:id"
render={ props => {
return (
<FormEntry key="2" title="edit item" />
);
}}
/>
</Switch>
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With