Understanding Lifecycle Methods by using React Class Components

If this is your first time learning about React, it's a JavaScript library for building user interfaces. It is declarative, efficient, and flexible. React Class Components which are reusable and can be composed to make complex UIs, for a while were the building blocks of React applications (still used for cases such as Error Boundaries which will be a topic for another day).

Note: React Hooks, now recommended by the documentation to be used instead, lets you use state and other React features without writing a class. Hooks are functions that let you “hook into” React state and lifecycle features from function components. So keep in mind that lifecycle methods are only available to class components.

Let's take a look at how React Components can help you understand how the lifecycle methods work. While it's not a need to use the lifecycle methods at every instance, it's important to know them when you do need them.

Using your own IDE/code editor, browser dev tool and this example below, let's take a look at where these methods appear within each of these three phases.

There are three different phases of the React Lifecycle and each phase has methods that control the behavior of the component.

  1. Mounting - Component being added to the DOM (Document Object Model) for the first time

    • `constructor()`: this method is called before the component is mounted to the DOM. It is typically used for initializing state and binding event handlers.

    • `render()`: happens when the component renders initially and when it re-renders due to a change in state or props from a parent or child component.

    • `componentDidMount()`: called after the component has been mounted successfully to the DOM. Typically used for making API calls or setting up event listeners.

  2. Updating - Component's props and state changing, having the component re-render

    • `shouldComponentUpdate(nextProps, nextState)`: this method gets called before the component re-renders and allows you to prevent rendering if you know that props and state haven't changed. Returns true by default but an implementation that returns false will cancel the component(and its children) and pending lifecycle methods from rendering.

    • `componentDidUpdate(pre props, prevState, snapshot)`: this method gets called after the component has rendered and updated the DOM. Useful for things that need to be done after the component's state or props have changed, such as making API calls as well as updating the DOM. The snapshot argument comes from the `getSnapshotBeforeUpdate` method, which gets called after the render method but before the changes are applied to the DOM.

  3. Unmounting - Component being removed from the DOM

    • `componentWillUnmount()`: this method gets called when the component is going to be unmounted. Used to clean up any resources or event listeners created in the `componentDidMount()` method.
import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    console.log('State initialized: ', this.state);
    this.state = {
      count: 0
    };
    console.log('constructor');
  }

  componentDidMount() {
    console.log('componentDidMount: ', 'Mounted');
  }

  // This will run when you click on increment or decrement.
  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate: ', 'Deciding to update');
    return true 
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('componentDidUpdate:', 'Updated.')
    // console.log('snapshot:', snapshot)
  }

  componentWillUnmount() {
    console.log('componentWillUnmount: ', 'Adios (Goodbye).')
  }

  increase = () => {
    this.setState({
      count: this.state.count + 1
    });
  }

  decrease = () => {
    this.setState({
      count: this.state.count - 1
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.decrease}>-</button>
        <span> {this.state.count} </span>
        <button onClick={this.increase}>+</button>
      </div>
    );
  }
}

export default Counter;

In addition to these lifecycle methods, several other methods can be used to control the behavior of a React component. For example, the getSnapshotBeforeUpdate(prevProps, prevState) I mentioned before which is called between rendering and committing to the DOM allows you to do calculations based on the previous DOM, and the static getDerivedStateFromProps() method can be used to update the component's state based on its props. Note the static keyword before the method else it won't work. Some of the other methods you'll find have been deprecated at this point so no use in focusing on those. There is another article where we will go on some of the use cases for some of these methods.

Overall, the lifecycle methods of a React component provide a useful set of tools for controlling the behavior of the component at different points in its lifetime. By using these methods, developers can create highly interactive and responsive UI elements that are easy to maintain and reuse.