简体   繁体   中英

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

<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>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM