Using componentDidUpdate() in React — Developer's Guide

Fortune Ikechi
June 6, 2022
Try Memberstack for Free!

TABLE OF CONTENTS
GET STARTED
Try Memberstack

The componentDidUpdate() method is an update method that is invoked after the componentDidMount() method and this happens immediately after an update occurs and not for the initial render. This article takes a deep look at componentDidUpdate() which is one of the methods in the Updating phase.

Every component in React has a life cycle that can be monitored and manipulated. These life cycles can be divided into three main phases and they are the Mounting, Updating and Unmounting phase.

The mounting or birth of a React component starts off the life cycle of the component. This is the phase in which we configure the state of the application and display the UI. It is during this stage that our props are defined. The methods used during the mounting phase includes constructor(), render(), componentDidMount() and getDerivedStateFromProps()

After the birth of the component in the mounting stage, the application is then ready for the Updating stage. At this stage, data updates are received and user actions are acted on. Updating Methods include shouldComponentUpdate(), render(), getSnapshotBeforeUpdate() and componentDidUpdate(). A component is said to be updated when a change occurs in the state or props.

The Unmounting also known as the death of a React component, is the phase where our component is removed from the DOM. The method used in this phase is the componentwillUnmount() method

In this article, we are going to take a deep look at componentDidUpdate() which is one of the methods in the Updating phase.

What is the componentDidUpdate() method

The componentDidUpdate() method is an update method that is invoked after the componentDidMount() method and this happens immediately after an update occurs and not for the initial render.

It should be noted that it's not exactly 100% true and correct to say that componentDidUpdate() is called after componentDidMount().

The componentDidMount() is called in the Mounting phase, while componentDidUpdate() is called in the Updating phase. Meaning that some methods like getSnapshotBeforeUpdate() might be called between componentDidMount() and componentDidUpdate().The update can be whenever a state mutation occurs or whenever there are changes to props.

Whenever a mutation or change happens, the componentDidUpdate() method gets the previous state and the previous props as arguments. By getting the previous state and previous props as arguments, this method allows us to check whether a condition has been met and then carry out a specific action if the check returns true.

The syntax of this method is:


componentDidUpdate(prevProps, prevState) {
 if (this.props.data !== prevProps.data) {
   console.log(this.props.data);
 }
}


Most times and on very rare occasions, the componentDidUpdate() method will be called after the getSnapshotBeforeUpdate() method and when this happens, a third argument -snapshot- is passed into the componentDidUpdate() method:


componentDidUpdate(prevProps, prevState, snapshot) {
 if (this.props.data !== prevProps.data) {
   console.log(this.props.data);
 }
}

How “not” to use componentDidUpdate() method

You should not set an unchecked state inside the componentDidUpdate() method. An example of an unchecked state is shown below:


componentDidUpdate(prevProps, prevState) {
  let value = this.props.data;
  this.setState({ isUpdated: false });// VERY BAD: DO NOT DO THIS!!!
}


The reason for this is that if we used the above code, we would enter into an infinite render loop because we first render then call update which then sets the state thereby triggering another render and so on.

The solution for this is to wrap your state in conditional statements and then to only change the state in specific areas as we will see in the example below:


componentDidUpdate(prevProps, prevState) {
  let value = this.props.data;
  if (this.state.value === value){
  this.setState({ value: '' });// A possible fix!!!
  }
}


Examples of componentDidUpdate()

In the example below, we have a click handler which is triggered whenever a button is clicked in the application which then changes the state of the clicked to the opposite of the current state.


import React from 'react';
class Counter extends React.Component {
  state = {
    clicked: false,
  };

  buttonPress = () => {
    this.setState({
      clicked: !this.state.clicked,
    });
  };
  componentDidUpdate(prevProps, prevState) {
    prevState.clicked === this.state.clicked
      ? console.log('same state')
      : console.log('changed clicked state');
  }
  render() {
    return (
      <React.Fragment>
        <button
          style={{
            margin: 'auto',
            width: '50%',
            padding: 20,
            marginTop: '10%',
            border: 'solid 1px black',
            textAlign: 'center',
            fontSize: 18,
            color: 'black',
            cursor: 'pointer',
          }}
          onClick={this.buttonPress}
        >
          Click me
        </button>
      </React.Fragment>
    );
  }
}
export default Counter;


From the example above, we see that the componentDidUpdate() method gets the previous state as a parameter and then checks to make sure that the previous state is the same as the current state of clicked and then logs the appropriate message to the console. if the state wasn't updated, that message would be different.

UseCases of the componentDidUpdate() method

Working with the DOM

One of the ways we can make use of the componentDidUpdate() method is when working with the DOM. Since the componentDidUpdate() method gets called after the Mounting phase, it means that we can also access DOM nodes in it. We can make use of the method to operate on the DOM when the component has been updated as we can see in the example below:


import React from 'react';
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter: 39 };
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({ counter: 39 + 4 });
    }, 2000);
  }
  componentDidUpdate(prevState, prevProps) {
    if (prevState !== this.state) {
      document.getElementById('mydiv').innerHTML =
        'The updated counter is ' + this.state.counter;
    }
  }
  render() {
    return (
      <div>
        <h1>My counter says: {this.state.counter}</h1>
        <div id="mydiv"></div>
      </div>
    );
  }
}
export default Counter;


From the above example we can see the Mounting and Updating phase of our component lifecycle. We created our application’s state, then we called the componentDidMount() method, updated our state and then set a timeout so that we can keep track of our component lifecycle. The componentDidUpdate() method was called after the componentDidMount() method. In it, we got our previous state and previous props as arguments. Then we checked if the previous state is not equal to the current state. As the condition returned true, we accessed the DOM and set the inner HTML of the div to a message of our choice.

Fetching data from Server / API Calls

Another use case for the componentDidUpdate() method is making server calls or querying an API endpoint. The reason this method is useful for this is because it fetches more data without refreshing the page, after the initial fetch on page load.


import React from 'react';
class Counter extends React.Component {
  // The first state lives here 
}

class ProjectsComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { projects: [] };
  }
  // Emulates fetching data from server, data is returned after 300 ms timeout
  fetch = (person) => {
    setTimeout(() => {
      this.setState({
        projects:
          person === 'Isaac'
            ? ['Create a dashboard with React', 'Play Monopoly with friends']
            : [
                'Work on a project with Isaac',
                'Win a game of chess against a grandmaster',
              ],
      });
    }, 300);
  };
  componentDidUpdate(prevProps, prevState) {
    // check whether person has changed
    if (prevProps.person !== this.props.person) {
    // fetch if the person has changed
      this.fetch(this.props.person);
    }
  }
  render() {
    // render a list of projects
    return (
      
    );
  }
}
export default Counter;


Below is a link to a codesandbox which has the complete code :

tps://codesandbox.io/s/blissful-breeze-w12rps

In the example above, we created a fetch function that emulates the use of fetch or axios. In the componenDidUpdate() method, we check if the person’s name has changed by comparing the previous props with the current props. If there is a change in the person’s name, we request a list of projects and then we update the component’s state with the projects

It should be noted that we don't update the component’s internal state so as to avoid an infinite update loop and that's why we check the name of the person in props to avoid that.

Conclusion

In this article, we have taken a good look at the componentDidUpdate method, its quirks, examples and use cases. We also looked at bad practices when working with the componentDidUpdate method and solutions to them. I hope this article provides answers to questions you may have about the componentDidUpdate() method while providing a better understanding of how it works.