简体   繁体   中英

React lifecycle methods not trigger, is there some hack behind lifecycle methods?

Today I found something like which I was not expected. This does not happen in Angular or maybe another JS library/framework. But today I was shocked when React lifecycle methods not triggered. Is there some hack behind it. let's see the code.

I have a component A

import React, { Component } from 'react'

class A extends Component {
  componentDidMount() {
    console.log('component mount', this.props.name);
  }

  render() {
    return (
      <>
        Hello - {this.props.name}
      </>
    )
  }
}

export default A;

I initialized that component twice in App component with some conditions:

import React, { Component } from 'react';
import { render } from 'react-dom';
import A from './A';
import './style.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      isShow: true
    };

    this.setIsShow = this.setIsShow.bind(this);
  }

  setIsShow() {
    this.setState(() => {
      return {isShow: !this.state.isShow};
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.setIsShow}>Show A1</button>
        <button onClick={this.setIsShow}>Show A2</button>
        <br />
        <br />
        {this.state.isShow ? <A name="A1" /> 
        :
        <A name="A2" />
        }
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

Now, what is expected behavior? name props value changed when I clicked on buttons. that's expected, alright. But there is no lifecycle method called when component reinitialized:(. The componentDidMount fire only once.

Now add key property in A component selector and you will see componentDidMount called on every time whenever A component reinitialized.

{
 this.state.isShow ? <A name="A1" key="1" /> 
 :
 <A name="A2" key="2" />
}

This is the expected behavior. But the question is why not without key property.

Checkout Online demo: https://stackblitz.com/edit/problem-react-lifecycle

What is happening here is react is optimizing the rendering for you. The same component is rendered with an updated prop vs unmounting and remounting with a different prop.

The lifecycle events are running just fine, you are just not seeing your console.log because componentDidMount is only fired on mount. If you use another lifecycle event like componentDidUpdate you will notice it fires on each change.

componentDidUpdate() {
  console.log("component update", this.props.name);
}

See a live example here

When you don't specify a key react will add one internally... if the component is the same then the same key would be generated for that component meaning it wont be unmounted. There is no need to undergo the extra overhead of unmounting and remounting essentially.

However, specifying a different key for the component forces the unmount and remount because to react you've told it that these should be treated as completely different components

Edited: This is because React is optimizing to not rerender the entire component. Adding another lifecycle method will show the expected output in the console

componentDidUpdate() {
  console.log('component update', this.props.name);
}

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