Airplane has been acquired by Airtable. Learn more →
gradient
The complete guide to React lifecycle hooks

The complete guide to React lifecycle hooks

Priya Patel
Growth Associate
Jul 12, 2023
7 min read

React components undergo a series of stages in their lifecycle, and within each of these stages, React provides hooks known as lifecycle hooks that enable various actions to be performed on each component. These actions include updating the component's state and cleaning up after the component has completed its lifecycle.

This article provides a comprehensive look at React lifecycle hooks, covering each hook in detail as well as offering guidance on when to use them and best practices to keep in mind.

Why you need lifecycle hooks

There are several advantages to using lifecycle hooks, including being able to reuse your components, increased performance optimization, and better scalability. In addition, by utilizing hooks such as componentDidMount, shouldComponentUpdate, componentDidUpdate, and componentWillUmount, users can effectively control a component's behavior and logic during its entire lifecycle, helping them write more maintainable and scalable components.

The following are some scenarios where React lifecycle hooks can provide several benefits.

Component initialization

Lifecycle hooks can be used to set up initial state values for the component. They can also be used to fetch data from an API and set up any necessary event listeners. For instance, when checking out online, an e-commerce page typically displays a list of the products you've added to your cart, along with their description, price, and other essential details. In React, the componentDidMount method can be used to set up the necessary state values for the component and fetch the necessary data from the API, which is eventually rendered on the page. This hook ensures that the component is fully loaded before any data is rendered, making it a reliable and effective way to handle complex rendering scenarios.

Component updates

To ensure that the component reflects the latest data, it needs to be updated as its state values and props change. This is where the lifecycle hooks shouldComponentUpdate and componentDidUpdate can help. For instance, in the previous e-commerce example, if an item is out of stock or removed from the cart, the component must be updated to reflect this change. With the shouldComponentUpdate and componentDidUpdate lifecycle hooks, users can re-fetch data from the API and ensure that the component can be efficiently updated and re-rendered to reflect the most recent state of the application.

Cleaning up components

To prevent memory leaks or update a parent component's state, it's essential to clean up resources like event listeners and timeouts with the componentWillUnmount lifecycle hook when a component is no longer in use. For instance, when a user checks out and completes the payment process online, the cart page needs to be reset, the item count in the parent component must be updated to zero, and async processes (like pending API calls) have to be aborted. The componentWillUnmount lifecycle hook can complete these tasks, ensuring that any resources used by the component are properly cleaned to avoid unwanted behavior.

React lifecycle hooks

React lifecycle hooks are categorized based on three component lifecycle stages: mounting, updating, and unmounting.

Mounting

Mounting is the first stage of a component's lifecycle, where it's created and inserted into the DOM. At this stage, we can initialize states and methods needed by the component.

Before the component is mounted, the states and methods are initialized using the constructor method, after which the component is rendered to the DOM. The constructor method accepts props as its argument and usually accesses the component's parent's data using the super(props) method.

The constructor method should be a pure function. It's not recommended to perform side effects in the constructor method because it can lead to unexpected behaviors, such as errors or memory leaks from async processes. Instead, the componentDidMount hook or the componentDidUpdate hook can be used.

After the component has been rendered, the componentDidMount method is used to perform additional setups, such as fetching data from the API.

Here's a code snippet that fetches data from the API and initializes the number of items a user has in their cart:

javascript

When using the componentDidMount method, we should avoid mutating state, as this could lead to endless re-renders. In this scenario, it would be better to use the componentDidUpdate hook.

In addition, this hook only executes once (when the component is mounted), and it's not recommended to write logic that would execute periodically. Moreover, since this hook runs after the component is mounted, it's common to make initial API calls in it. For subsequent API calls, componentDidUpdate should be used.

Updating

Updating is the second stage of the lifecycle and takes place after the component has been created. In this stage, the component updates as the state or props of the component changes. There are two lifecycle hooks in this stage:

  1. shouldComponentUpdate is run before the component re-renders and is meant for performance optimization. It can be used to determine whether or not a component should re-render. It takes in two arguments: nextProps and nextState. These arguments are usually compared against the current props or state and eventually return a Boolean value. This value is used to decide whether or not the component should re-render. If true, the component re-renders.
  2. componentDidUpdate is run after the component has been updated and takes in three optional arguments: prevProps, prevState, and the snapshot. Usually, the previous props or previous state arguments are compared to the current state, and the logic is executed based on the result of this comparison.

Below is a code snippet to demonstrate the use of the componentDidUpdate lifecycle hook. This hook accepts the previous state (total number of items in the cart) as an argument and checks if the current number of items in the cart is less than before the update. Based on this condition, it then indicates whether or not an item has been removed:

javascript

As advised by the React team, we shouldn't rely on the shouldComponentUpdate hook to prevent re-rendering because it can lead to unexpected bugs. This is because the hook makes a shallow comparison between the current props/state and the next, which can be a problem for deeply nested objects. In addition, if a child component's state changes, the hook cannot prevent it from re-rendering.

Moreover, when using componentDidUpdate, we need to set state (using the setState method) only inside a comparison block. This comparison is usually between the prevState/prevProps and the current one.

It's important to note that for a component, if the shouldComponentUpdate hook returns false, then the logic inside the componentDidUpdate hook will not be executed.

Unmounting

Unmounting is the final stage of a component's lifecycle. This is where the component is removed from the DOM and cleanups (ie, removing event listeners and clearing timers) typically occur. At this stage, the componentWillUnmount hook is used and is invoked immediately before the component is removed from the DOM.

Below is a code snippet to illustrate the use of componentWillUnmount. The hook cleans up the component by removing the scroll event, as it will no longer be useful after the component is removed from the DOM:

javascript

When using componentWillUnmount, we shouldn't set state or modify props inside the hook because the hook ends the lifecycle of the component and no logic will be processed after that. In addition, we should cancel subscriptions such as asynchronous tasks and connections to a database, as this helps improve performance and prevent memory leaks.

Here's a typical flow for a component's lifecycle:

To learn more about React components, check out our blog for content such as understanding the React component lifecycle, how to build a React component library, and more.

Introducing Airplane: build custom UIs

Airplane is the developer platform for building custom internal tools. With Airplane, you can transform SQL queries, Python scripts, APIs, and more into workflows and UIs.

Airplane Views is a React-based platform that makes it easy to build custom UIs quickly. Airplane's pre-built component and template libraries allow users to build UIs within minutes. Since Airplane is a code-first platform, everything you build can be integrated with the rest of your codebase, version controlled, and integrated with third parties.

To try it out and build your first React-based View in minutes, sign up for a free account or book a demo.


Author: Paul Ibeabuchi

Paul Ibeabuchi is a Frontend Engineer skilled with knowledge on UI designs. He's curious and enjoys finding out the "why" of things. He is able able to build functional web applications and easily convert UI designs into pixel perfect responsive web pages.

Share this article:
Priya Patel
Growth Associate
Priya is currently a Growth Associate at Airplane. Before that, she was a Strategy Manager at Salesforce.

Subscribe to new blog posts from Airplane.