React Component Lifecycle

React Lifecycle
Reading Time: 5 minutes

A react component has certain lifecycle methods in which we can insert our own code and execute it at a particular moment during the lifecycle of the component. A react component can go through different sets of lifecycle methods depending upon in which phase the component is. These Phases are Mounting, Updating, and Unmounting.

Mounting

Following is the order of execution for the methods, when the component is created and inserted into the real DOM:

  • constructor()
  • getDerivedStateFromProps()
  • render()
  • componentDidMount()

Note: When we talk about mounting, we’re talking about the process of converting the virtual components into actual DOM elements that are placed in the DOM by React.

Flow diagram for mounting phase

Constructor

constructor(props)

When a component is being created, before anything else the constructor() method is called. This the place where we can set the local state and initialize values.

Caution: Avoid introducing any side-effects or subscriptions in the constructor.

getDerivedStateFromProps

static getDerivedStateFromProps(props, state)

A rarely used method, this method is called right before rendering the elements into DOM.

It takes the state as an argument and returns an object with changes to the state.  It should return an object to update the state, or null to update nothing.

This method exists for the rare use cases where the state depends on changes in props over time. For example, it might be handy for implementing a <Transition> the component that compares its previous and next children to decide which of them to animate in and out.

No side effects should be caused in this methods.

Render

render()

The render() method is the only required method out of all lifecycle methods. This is the method that actually outputs the HTML to the DOM.

render() should return one of the things out of:
– React elements. (created via JSX)
– Array of React elements.
– Strings and numbers.
– Boolean or null.

No side effects should be caused in this method.

componentDidMount

componentDidMount()

The componentDidMount() is called after the component is rendered. This the place where side effects can be caused.

If you need to load data from a remote endpoint, this is a good place to instantiate the network request. This method is a good place to set up any subscriptions.

But state should not be set here as it will cause to re-render the component and cause performance issues.

Note: componentDidMount() will only execute after the child component inside it has been rendered and their individual lifecycle has been completed till componentDidMount().

Example:

This is a simple example to show the lifecycle of the react component in the mount phase in action. Here console.log at each method will depict the flow of execution of each method.

import React, {Component} from 'react';
import './App.css';
import Child from "./childComponent/child";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      randomNumber: 0,
    };
    console.log('[App] constructor()')
  }

  static getDerivedStateFromProps(props, state) {
    console.log('[App] getDerivedStateFromProps')
    return null;
  }

  componentDidMount() {
    setTimeout(() => {
      console.log('[App] componentDidMount')
    }, 1000)
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('[App] componentDidUpdate')
  }

  genRandomNum = () => {
    this.setState({randomNumber: Math.random()})
  }

  render() {
    console.log('[App] render()')
    return (
        <div>
          <div>Parent Component</div>
          <button onClick={() => this.genRandomNum()}>generate a random number</button>
          <Child randomNumber={this.state.randomNumber}/>
        </div>);
  }
}

export default App;

Output:

Updating

The component updated where there are changes in props and state.

The following built-in methods get called in the following order when a component gets updated.

  • getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()
Flow diagram for Updating phase.

getDerivedStateFromProps

static getDerivedStateFromProps(props, state)

This method gets called both when the component gets mounted and on subsequent updates. And still, it is a good place to set the state based on props.

shouldComponentUpdate

shouldComponentUpdate(prevProps, nextProps)

This method lets react know whether to update and re-render the component or not. It returns a boolean value to specify whether to update or not, the default is true. This method is really useful to optimize the performance by avoiding the constant re-render of components every time.

You can make your own logic based on the previous and next props that updated, to check whether the component should update or not and return true or false.

render

render()

render() gets called if shouldComponentUpdate return true and it re-renders the HTML on the DOM with the updates.

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate() is invoked right before the rendered output is committed to the DOM. It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed. Any value returned by this lifecycle will be passed as a parameter to componentDidUpdate().

This use case is not common, but it may occur in UIs like a chat thread that needs to handle scroll position in a special way.

A snapshot value (or null) should be returned.

componentDidUpdate

componentDidUpdate(prevProps, prevState, snapshot)

This method is invoked once the update is done. It takes in the previous props, previous state, and snapshot as input. This is the perfect place to cause side effects and make network requests for the updated props.

It may happen that the state is also updated in this method and in this case, it will cause a re-render and then again cause componentDidUpdate() to execute and update the state again. This will cause an infinite loop. To stop this, such code inside the componentDidUpdate which updates the state should be wrapped up in a condition that compares the previous and new props.

Example:

Below is the code for the child component from the previous example with all the lifecycle methods for the update phase.

import React, {Component} from 'react';

class Child extends Component {

    constructor(props) {
        super(props);
        this.state = {};
        console.log('[Child] constructor()')
    }

    static getDerivedStateFromProps(props, state) {
        console.log('[Child] getDerivedStateFromProps')
        return null;
    }

    componentDidMount() {
        setTimeout(() => {
            console.log('[Child] componentDidMount')
        }, 1000)
    }

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log('[Child] shouldComponentUpdate')
        return true
    }

    getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log('[Child] getSnapshotBeforeUpdate')
        return null
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('[Child]  componentDidUpdate')
    }

    render() {
        console.log('[Child] render()')
        return (<div>Child Component {this.props.randomNumber}</div>
        );
    }
}

export default Child;

Now when we generate a new random number, we will update the props in the child component and hence trigger the lifecycle for update

output:

So after the render() of the App component (i.e parent component) the update cycle starts for the child component and after the componentDidUpdate for a child is executed, componentDidUpdate for the parent component is executed and then the lifecycle for the parent ends.

Unmounting

When a react component is being removed from the DOM only one built-in method is called.

componentWillUnmount

componentWillUnmount()

Before the element is removed, this method is called. This is a good place to perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().

Lifecycle diagram cheat sheet.

(image source: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)

References:

React.js documentation: https://reactjs.org/docs/react-component.html

Check out more about react:

React hooks of a functional component: https://blog.knoldus.com/react-hooks-introduction-part-1/

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading