Ultimate Guide to React.js Lifecycle Methods with Code Examples

React.js is one of the most popular JavaScript libraries for building user interfaces, particularly for single-page applications. Understanding the lifecycle methods of a React component is crucial for creating dynamic, high-performance applications. These methods allow developers to hook into different stages of a component's lifecycle, from its initial rendering to its removal from the DOM. In this article, we'll explore the React.js lifecycle methods in detail, with easy-to-understand examples and code snippets.

What are React.js Lifecycle Methods?

React.js lifecycle methods are functions that get invoked at different phases of a component's lifecycle. These phases are:

  1. Mounting: When the component is being inserted into the DOM.

  2. Updating: When the component is being re-rendered due to changes to props or state.

  3. Unmounting: When the component is being removed from the DOM.

Mounting Phase

During the mounting phase, a component is created and inserted into the DOM. React provides four lifecycle methods during this phase:

  1. constructor()

  2. static getDerivedStateFromProps()

  3. render()

  4. componentDidMount()

1. constructor()

The constructor method is called before anything else, when the component is first created. It’s typically used to initialize the state or bind event handlers.

javascriptCopy codeclass MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
    this.incrementCounter = this.incrementCounter.bind(this);
  }

  incrementCounter() {
    this.setState({ counter: this.state.counter + 1 });
  }

  render() {
    return <button onClick={this.incrementCounter}>Click Me: {this.state.counter}</button>;
  }
}

2. static getDerivedStateFromProps(props, state)

This static method is rarely used, but it's called right before rendering, both during the initial mount and subsequent updates. It returns an object to update the state or null to update nothing.

static getDerivedStateFromProps(props, state) {
  if (props.initialValue !== state.value) {
    return { value: props.initialValue };
  }
  return null;
}

3. render()

The render() method is the only required method in a class component. It returns the JSX that represents the component’s UI.

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

4. componentDidMount()

This method is invoked immediately after a component is mounted. It's a good place to make network requests, start animations, or set up subscriptions.

componentDidMount() {
  fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => this.setState({ data }));
}

Updating Phase

The updating phase occurs when a component's state or props change. The following methods are called during this phase:

  1. static getDerivedStateFromProps()

  2. shouldComponentUpdate()

  3. render()

  4. getSnapshotBeforeUpdate()

  5. componentDidUpdate()

1. shouldComponentUpdate(nextProps, nextState)

This method lets you control whether the component should re-render or not. It should return a boolean value.

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

2. getSnapshotBeforeUpdate(prevProps, prevState)

This method is called right before the changes from the virtual DOM are to be reflected in the DOM. It allows you to capture some information (e.g., scroll position) before the DOM is updated.

getSnapshotBeforeUpdate(prevProps, prevState) {
  if (prevState.value !== this.state.value) {
    return this.inputRef.current.scrollHeight;
  }
  return null;
}

3. componentDidUpdate(prevProps, prevState, snapshot)

This method is called immediately after the DOM is updated. It's a good place to operate on the DOM or make further network requests based on the update.

componentDidUpdate(prevProps, prevState, snapshot) {
  if (snapshot !== null) {
    this.inputRef.current.scrollTop = this.inputRef.current.scrollHeight - snapshot;
  }
}

Unmounting Phase

The unmounting phase is when a component is being removed from the DOM. The following method is called during this phase:

  1. componentWillUnmount()

1. componentWillUnmount()

This method is called right before the component is removed from the DOM. It's a good place to clean up subscriptions, timers, or any other side effects.

componentWillUnmount() {
  clearInterval(this.timerID);
}

Complete Example: Counter Component

Let’s create a complete example that demonstrates the use of React.js lifecycle methods by building a simple counter component that fetches data from an API when it mounts, updates the title based on the counter value, and cleans up when the component is unmounted.

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    // Initialize state
    this.state = {
      count: 0,
      data: null
    };
    // Bind methods
    this.increment = this.increment.bind(this);
  }

  // Mounting: Fetch data when the component mounts
  componentDidMount() {
    console.log('Component did mount');
    // Fetch data from an API
    fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(data => this.setState({ data }))
      .catch(error => console.error('Error fetching data:', error));

    // Setting up a timer (example of resource that needs cleanup)
    this.timerID = setInterval(() => this.increment(), 1000);
  }

  // Updating: Decide whether the component should update
  shouldComponentUpdate(nextProps, nextState) {
    console.log('Should component update?');
    // Only update if the count is different
    return nextState.count !== this.state.count;
  }

  // Updating: Capture scroll position before the update
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log('Get snapshot before update');
    // Capture the scroll position (example usage)
    if (prevState.count !== this.state.count) {
      return document.body.scrollHeight;
    }
    return null;
  }

  // Updating: Perform side effects after the update
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('Component did update');
    // If we captured a snapshot, we could use it here (e.g., scroll to a position)
    if (snapshot !== null) {
      console.log('Scroll height before update:', snapshot);
    }
    // Update document title based on the count
    document.title = `Count: ${this.state.count}`;
  }

  // Unmounting: Clean up before the component is removed
  componentWillUnmount() {
    console.log('Component will unmount');
    // Clear the timer
    clearInterval(this.timerID);
  }

  // Method to increment the counter
  increment() {
    this.setState(prevState => ({
      count: prevState.count + 1
    }));
  }

  // Render the component
  render() {
    console.log('Render');
    const { count, data } = this.state;

    return (
      <div>
        <h1>Count: {count}</h1>
        {data ? <p>Fetched Data: {data.title}</p> : <p>Loading data...</p>}
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default Counter;

Conclusion

Understanding React.js lifecycle methods is key to building complex and efficient React apps. Each method has a specific role, letting developers run code at the right times in a component's lifecycle. By mastering these methods, you can create stronger, easier-to-maintain, and faster React apps.

Happy coding! 🚀

0
Subscribe to my newsletter

Read articles from Dhananjoy Mahata directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dhananjoy Mahata
Dhananjoy Mahata