The React component lifecycle in update stage: shouldComponentUpdate() and componentDidUpdate(): part 2

Following previous article about mounting stage in React component lifecycle, here we explain two important methods in the update stage. We will have a look at shouldComponentUpdate() and componentDidUpdate().

shouldComponentUpdate()

Generally shouldComponentUpdate() is considered a useful but tricky and sometimes confusing lifecycle method. We must know when should we use it and when not. Typically its use case is when we want to let React know that the component has not been affected by current state and props changes. So we tell React that the component may not need to re render:

shouldComponentUpdate(nextProps, nextState)

Technically by default in React component will re render in every state or props change. We need to remember shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.

update stage

updating stages

Practically we should not use shouldComponentUpdate() to prevent rendering. This method only exists as a performance optimization.

Instead we should use PureComponents which performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update.

Use cases

However we may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped.  We could return false  but it does not prevent child components from re-rendering when their state changes.

Therefor if it returns false render() and componentDidUpdate() will not be invoked:

shouldComponentUpdate(nextProps, nextState) {
  return this.state.value != nextState.value;
}

As an example we might have a state with large object with several properties. But we have a specific component that cares about a single property or a small portion of the state. Therefor we can check for that change to determine if the component needs to re-render:

shouldComponentUpdate(nextProps, nextState) {
    if (this.props.color !== nextProps.color) {
      return true;
    }
    if (this.state.count !== nextState.count) {
      return true;
    }
    return false;
}

componentDidUpdate()

Additionally we have componentDidUpdate() which is invoked immediately after updating occurs and is not called for the initial render:

componentDidUpdate(prevProps, prevState, snapshot)

Practically we can manipulate the DOM in componentDidUpdate() method. In addition we can create side effects and do network requests. However we should compare current props to the previous props for that matter:

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

But remember if we update state in componentDidUpdate() it should be wrapped in a condition like the example above to prevent infinite loops.

component lifecycle metods

Obviously just like componentDidMount(), the componentDidUpdate() is called after all of the children are updated

componentDidUpdate(prevProps, prevState) {
  // only update chart if the data has changed
  if (prevProps.data !== this.props.data) {
    this.chart = c3.load({
      data: this.props.data
    });
  }
}

As a result we better be careful when we decide which lifecycle method we need. Although shouldComponentUpdate() could help with the performance but it can be buggy. Certainly we should limit our usage of this method.

Also componentDidUpdate() is a great place for network calls but we better not use it to update states as it depends on conditions and might cause infinite looping and reduce performance. We will check other lifecycle methods in the next article.

Thank you for reading.

© 2019
Azadeh Faramarzi

This site is created and maintined by Azadeh Faramarzi , A passionate developer, sport and code lover who loves to share and write when she have some time.