DEV Community

Cover image for React Component Lifecycle
Jay Caetano
Jay Caetano

Posted on

React Component Lifecycle

Component is a building block of any React application and a React application is composed of multiple components. Lifecycle methods are used to interact with component at different point in the component life.

Generally a React Component’s life cycle can be divided into three categories:

  • Mounting
  • Updating
  • Unmounting

Let’s list down the order in which each life cycle method is called in the above mentioned categories and go through the details of each method later.

Mounting:

During the initialization of the component when the instance of the component is being created and inserted into the DOM, following methods are called in the same order in which they are listed:

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

Updating:

When component is re-rendered due to change in props or state etc, following methods are called:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

Unmounting:

On unmounting or removal of component from the DOM, only a single React life cycle method is called:

  • componentWillUnmount()

Lifecycle methods explained:

Now lets discuss in detail React component life cycle methods.

render():

Most important life cycle method and the only method which is compulsory for the react component. It should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser.

It returns a single element which represents the component during the rendering process and should either be a representation of a native DOM component (e.g. <p/>) or another user-defined component. If nothing should be rendered, it can return null or undefined.

This function will be recalled after any change to the component's props or state.

render() {
    return (
        <div>
            Hello World!
        </div>
    );
}

As mentioned earlier, it should not modify the component state meaning setState() cannot be defined in render(). If you will try to setState() it will keep on calling render again and again which will result in an infinite loop resulting in breaking the application.

componentDidMount():

Invoked immediately after a component is mounted meaning all the elements are rendered correctly. This method can be used for:

  • Fetching data
  • Adding event listeners
  • Manipulating DOM elements
  • Setting up subscriptions
import React, { Component } from 'react'; 

class App extends Component {
        constructor(props){
        super(props);
        this.state = { data: 'Michael Jordan' } 
    } 

    loadPageData (){
        setTimeout(() => {
                console.log('Our data is fetched'); 
        this.setState({ data: 'Hello…' }) 
        }, 1000) 
    } 

    componentDidMount(){ 
        this.loadPageData();
    } 

    render() { 
        return( <div> {this.state.data} </div> ) 
    } 
}

 export default App;

In the above example we are loading page data once our component is mounted. From the componnetDidMount() life cycle method, we are calling loadPageData() method, we are using setTimeout() to simulate network call. Once the data is fetched, we are using setState() to change state of the component and make it render.

getDerivedStateFromProps():

This method is only for rare use cases where the state depends on changes in props. It is called right before calling the render() method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.

shouldComponentUpdate():

This method is also called before render life cycle method only when new props or state are received. It either returns true or false. By default, return value is always true.

It is only added as a life cycle method for performance optimization. This method is not called during the initial render or when the forceUpdate() is called.

getSnapshotBeforeUpdate():

It is called right before the most recent changes to the DOM created by render() method takes effect. For example if we added multiple items to the list and before they are rendered, we want to get the scroll position of the last item of the previous list item, we can use this method to get that position.

This method is not commonly used. Any value retuned from this method will be passed to the componentDidUpdate() life cycle method as a parameter.

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // Snapshot value is only passed when there are new items.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}></div>
    );
  }
}

componentDidUpdate():

This method is the update version of ComponentDidMount(). It is called rite after the component update takes place, except the first time when the component is rendered.

componentDidUpdate() takes two arguments as parameters, prevProps and prevState. If the component has also implemented getSnapshotBeforeUpdate(), a third parameter ‘snapshot’ is also passed as parameter to this method.

componentDidUpdate(prevProps, prevState, snapshot) {
  if (this.props.Id !== prevProps.Id) {
    this.reloadData();
  }
}

componentWillUnmount():

This method is called right before when the component is going to be destroyed. In this lifecycle method we perform all the cleanup, like terminating network requests, unsubscribe to subscriptions, resetting timers etc.

setState() should not be called in this method and we are going to destroy our component.

import React, { Component } from 'react'; 
class Timer extends React.Component {
  constructor(props) {
    super(props);   
    this.state = {date: new Date()};
  }
  incrementTime() {   
    this.setState({
      date: new Date()
    });
  }
  componentDidMount() {
    this.timerInterval = setInterval(() => {
      this. incrementTime ();
    }, 1000);
  }
  componentWillUnmount() {
    clearInterval(this. timerInterval);
  }
  render() {
    return (        
        <div>It is {this.state.date.toLocaleTimeString()}.</div>
    );
  }
}

In this example we can see that we have rendered time interval on page and incrementing it using setInterval(). Now when component will destroy, we are clearing this interval in componentWillUnmount() life cycle method.

I hope you find this useful. If you have any questions or if you think I missed something please add a comment.

If you like this article, please leave a like or a comment.

You can follow me on Twitter or find my other writings on my personal website at jaycaetano.com.

Top comments (0)