Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: is componentDidUpdate same for 2 different instances of a component?

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

like image 844
TheSoul Avatar asked Oct 29 '22 20:10

TheSoul


1 Answers

<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>
}
like image 135
Badis Merabet Avatar answered Nov 15 '22 06:11

Badis Merabet