BairesDev
  1. Blog
  2. Software Development
  3. React Lifecycle: Methods & Hooks In Detail
Software Development

React Lifecycle: Methods & Hooks In Detail

React component lifecycle is an important concept to understand when developing applications with React. It allows developers to control and modify components throughout their life cycle, from creation to destruction. The react component lifecycle consists of several methods in different stages of a component’s existence. Understanding how these methods interact with each other can be [...]

Justice Erolin

By Justice Erolin

As BairesDev CTO, Justice Erolin translates BairesDev's vision into technical roadmaps through the planning and coordinating of engineering teams.

16 min read

react-lifecycle-hooks-methods-detail

React component lifecycle is an important concept to understand when developing applications with React. It allows developers to control and modify components throughout their life cycle, from creation to destruction. The react component lifecycle consists of several methods in different stages of a component’s existence. Understanding how these methods interact with each other can be critical for creating efficient and maintainable code.

This article will discuss React Component Lifecycle, why it matters, and how you can use its various methods effectively within your application development process. I’ll look at some of the key concepts behind React’s implementation of the lifecycles, including mounting , updating, unmounting, and errors. I will also provide examples of how best to use each one for maximum benefit in terms of performance optimization and bug prevention/resolution.

Before I move on, it’s worth noting an interesting fact about React’s popularity worldwide. According to the latest Stack Overflow Survey of 2022, 42.62% of developers reported using React more than any other library over the past year. This highlights React’s position as the go-to choice for building dynamic and scalable user interfaces.

What is a Component in React?

In React, a component is a building block for creating user interfaces. Components are essentially reusable pieces of code that can be combined together to create a more complex UI. A component can be considered a JavaScript function that returns a piece of code (often called JSX) representing a part of the UI.

There are two main types of components: functional components and class components. Functional components are simpler and more lightweight, while class components are more powerful and can access more features, such as state and lifecycle methods.

Here’s an example of a simple, functional component in React:

import React from 'react';

function Greeting(props) {
  return (
    <h1>Hello, {props.name}!</h1>
  );
}

export default Greeting;

In this example, the Greeting component is a functional component that takes in a name and returns an h1 element with the message “Hello,name!”.

The React Component Lifecycle

Are you new to React development and wondering how to manage the state of your components? Or maybe you’re an experienced developer looking to optimize your code and improve the user experience. Whatever your level of expertise, understanding the React component lifecycle is key to building robust and efficient applications. In this section, we’ll look at the different stages of the component lifecycle and the methods associated with each stage.

react-lifecycle

By the end, you’ll have a solid understanding of how components work in React by following a step-by-step case-based example so you can be well-equipped to build dynamic and engaging user interfaces.

The React component lifecycle can be divided into three main phases: Mounting, Updating and Unmounting. Each phase has various methods invoked at specific points in the component’s lifecycle.

Let’s now look at a table summarizing the different stages of the React component lifecycle and the methods associated with each stage:

Lifecycle Stage Methods
Mounting constructor()

static getDerivedStateFromProps()

render()

componentDidMount()

Updating static getDerivedStateFromProps()

shouldComponentUpdate()

render()

getSnapshotBeforeUpdate()

componentDidUpdate()

Unmounting componentWillUnmount()
Error Handling static getDerivedStateFromError()

componentDidCatch()

 

Now that we know the stages of a React component lifecycle, let’s explore each of its methods in more detail to gain a deeper understanding of how they work and what they’re used for.

Mounting

The mounting phase occurs when a component is created and inserted into the DOM. During this phase, the following methods are invoked:

constructor()

When a component is created, the constructor method is the first to be called. It is used to initialize the component’s state and bind event handlers.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick() {
    this.setState({ count: this.state.count + 1 });
  }
  
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.handleClick}>Click me</button>
      </div>
    );
  }
}

getDerivedStateFromProps()

This method is called right after the constructor, allowing the component to update its state based on changes to its props. This method should return an object to update the state or null if no update is needed.

class MyComponent extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.value !== prevState.value) {
      return { value: nextProps.value };
    }
    return null;
  }
  
  constructor(props) {
    super(props);
    this.state = {
      value: props.value
    };
  }
  
  render() {
    return <div>{this.state.value}</div>;
  }
}

render()

This method is responsible for rendering the component’s UI. It should return a React element, a JSX expression, or a call to React.createElement().

class MyComponent extends React.Component {
render() {
return <div>Hello, {this.props.name}!</div>;
}
}

componentDidMount()

This method is called after the component has been rendered for the first time. It performs any side effects, such as fetching data from an API or setting up event listeners.

class MyComponent extends React.Component {
  componentDidMount() {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  }
  
  render() {
    return (
      <div>
        {this.state.data ? (
          <ul>
            {this.state.data.map(item => <li key={item.id}>{item.name}</li>)}
          </ul>
        ) : (
          <p>Loading data...</p>
        )}
      </div>
    );
  }
}

Updating

The updating phase occurs when a component’s props or state changes. During this phase, the following methods are invoked:

getDerivedStateFromProps()

This method is called again if the component’s props change. It works the same as in the mounting phase, allowing the component to update its state based on changes to its props.

class MyComponent extends React.Component {
    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.value !== prevState.value) {
            return {
                value: nextProps.value
            };
        }
        return null;
    }

    constructor(props) {
        super(props);
        this.state = {
            value: props.value
        };
    }

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

shouldComponentUpdate()

This method is called before the component is updated, allowing the component to determine whether it should re-render. It should return a boolean value indicating whether the component should update or not.

class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.value !== this.props.value;
  }
  
  render() {
    return <div>{this.props.value}</div>;
  }
}

render()

This method is called again if the component is re-rendered. It should return a new React element that reflects the updated state of the component.

class MyComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}!</div>;
  }
}

getSnapshotBeforeUpdate()

This method is called right before the component is updated and allows the component to capture some information from the DOM before it changes. This information is then passed to componentDidUpdate().

class MyComponent extends React.Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.value !== this.props.value) {
      return this.myRef.current.getBoundingClientRect().top;
    }
    return null;
  }
  
  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot !== null) {
      console.log(`Element was ${snapshot}px from the top`);
    }
  }
  
  render() {
    return <div ref={this.myRef}>Hello, {this.props.name}!</div>;
  }
}

componentDidUpdate()

This method is called after the updated component. It is used to perform any side effects, such as updating the DOM or dispatching an action to a Redux store.

class MyComponent extends React.Component {
  componentDidUpdate(prevProps, prevState) {
    if (prevProps.value !== this.props.value) {
      this.props.onValueChange(this.props.value);
    }
  }
  
  render() {
    return <div>{this.props.value}</div>;
  }
}

Unmounting

The unmounting phase occurs when a component is removed from the DOM. During this phase, the following method is invoked.

componentWillUnmount()

The componentWillUnmount method is called right before the component is removed from the DOM. It is used to perform any cleanup tasks, such as removing event listeners or canceling API requests.

class MyComponent extends React.Component {
  componentDidMount() {
    this.intervalId = setInterval(() => {
      this.setState({ time: new Date() });
    }, 1000);
  }
  
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }
  
  render() {
    return <div>The time is {this.state.time.toLocaleTimeString()}.</div>;
  }
}

In addition to the lifecycle methods for component creation, update, and removal, React provides two methods for error handling: static getDerivedStateFromError() and componentDidCatch().

Error Handling

React components can also have errors during their lifecycle. An error in a child component can propagate up to the parent component. To handle these errors, React provides two methods.

static getDerivedStateFromError()

The static getDerivedStateFromError() method is a lifecycle method called when there is an error during rendering, in the lifecycle methods of child components or the constructors of any child component. It allows the component to update its state with an error message, which can then be used to render a fallback UI.

class MyComponent extends React.Component {
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong.</div>;
    }

    return <div>{this.props.children}</div>;
  }
}

class App extends React.Component {
  render() {
    return (
      <MyComponent>
        <ChildComponent />
      </MyComponent>
    );
  }
}

componentDidCatch()

The componentDidCatch() method is a lifecycle method that is called when an error is caught in a child component. It allows the component to perform side effects, such as logging the error or sending an error report to a server.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    // Log the error to an error reporting service
    logErrorToMyService(error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong.</div>;
    }

    return <div>{this.props.children}</div>;
  }
}

class App extends React.Component {
  render() {
    return (
      <MyComponent>
        <ChildComponent />
      </MyComponent>
    );
  }
}

React Component Life Cycle Example: A WeatherApp

react-lifecycle-weather-app-mockup

After understanding how the React component lifecycle methods work and what they’re used for, let’s put that knowledge into practice with an example. In this tutorial, we’ll create a simple React app that displays the current weather based on the user’s location. We’ll explore how to use the component lifecycle methods to handle mounting, updating, unmounting, and error handling, giving you a real-world example of integrating these concepts into your applications.

Prerequisites

Before we begin, make sure you have the following installed on your computer:

  • Node.js (version 10 or higher)
  • npm (version 6 or higher)
  • A react code editor of your choice (e.g. Visual Studio Code)

Getting Started

To get started, open your terminal and create a new React app using the create-react-app command:

npx create-react-app weather-app

Once the app is created, navigate to the project directory and start the development server:

cd weather-app
npm start

Your app should now be running at http://localhost:3000.

react-lifecycle-methods-example-app

Creating the WeatherApp Component

To create the WeatherApp component, create a new file named WeatherApp.js in the src  folder. Open the src/App.js file in your code editor and replace the existing code with the following.

import React from 'react';
import Weather from './components/Weather';

function App() {
  return (
    <div className="App">
      <WeatherApp />
    </div>
  );
}

export default App;

Now add the following code to the src/WeatherApp.js file.

import React, { Component } from 'react';

class WeatherApp extends Component {
  render() {
    return (
      <div>
        <h1>Current Weather</h1>
      </div>
    );
  }
}

export default WeatherApp;

This creates a simple React component that renders a heading.

react-lifecycle-methods-example-weather-app

Handling the User’s Location

To fetch the user’s location, we will use the Geolocation API provided by the browser. We will use the componentDidMount() lifecycle method to fetch the location when the component is mounted.

import React, { Component } from 'react';

class WeatherApp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      latitude: null,
      longitude: null
    };
  }

  componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        const { latitude, longitude } = position.coords;
        this.setState({ latitude, longitude });
      },
      (error) => {
        console.error(error);
      }
    );
  }

  render() {
    const { latitude, longitude } = this.state;

    return (
      <div>
        <h1>Current Weather</h1>
        <p>Latitude: {latitude}</p>
        <p>Longitude: {longitude}</p>
      </div>
    );
  }
}

export default WeatherApp;

In the componentDidMount() method, we use the getCurrentPosition() method of the Geolocation API to fetch the user’s location. This method takes two callbacks: one to handle success and one to handle the error. If the location is fetched successfully, we update the component state with the latitude and longitude values. If there is an error, we log it to the console.

In the render() method, we render the latitude and longitude values from the component state.

 

react-lifecycle-example-current-weather

Fetching Weather Data

To fetch the current weather data based on the user’s location, we will use the OpenWeatherMap API. We will use the fetch() method to make the API request. We will also use the componentDidMount() method to fetch the weather data when the component is mounted.

import React, { Component } from 'react';

const API_KEY = 'YOUR_API_KEY';

class WeatherApp extends Component {
constructor(props) {
  super(props);
  this.state = {
    latitude: null,
    longitude: null,
    weatherData: null
  };
}

componentDidMount() {
  // Fetch the user's location
  navigator.geolocation.getCurrentPosition(
    (position) => {
      const { latitude, longitude } = position.coords;
      this.setState({ latitude, longitude });

      // Fetch the weather data
      const url = `http://api.weatherstack.com/current?access_key=${API_KEY}&query=${latitude},${longitude}`;
      fetch(url)
        .then(response => response.json())
        .then(data => this.setState({ weatherData: data }))
        .catch(error => console.error(error));
    },
    (error) => {
      console.error(error);
    }
  );
}
 render() {
  const { latitude, longitude, weatherData } = this.state;

  return (
    <div>
      <h1>Current Weather</h1>
      {latitude && longitude && (
        <p>
          Latitude: {latitude}, Longitude: {longitude}
        </p>
      )}
      {weatherData && (
        <div>
          <p>Temperature: {weatherData.current.temperature}°C</p>
          <p>Description: {weatherData.current.weather_descriptions[0]}</p>
        </div>
      )}
    </div>
  );
}
}

export default WeatherApp;

In the componentDidMount() method, we first fetch the user’s location using the getCurrentPosition() method. Once we have the latitude and longitude values, we use them to construct the URL for the API request. We also pass in our API key and set the units parameter to metric to get temperature values in Celsius.

We then use the fetch() method to make the API request. We use the then() method to handle the response and convert it to JSON format. We then update the component state with the weather data. If there is an error, we log it to the console.

In the render() method, we conditionally render the latitude and longitude values and the weather data based on whether they exist in the component state.

react-lifecycle-example-current-weather-with-location

Error Handling

Finally, let’s handle errors that may occur during the component’s lifecycle. We will use the static getDerivedStateFromError() and componentDidCatch() methods to handle errors.

import React, { Component } from 'react';

const API_KEY = 'YOUR_API_KEY';

class WeatherApp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      latitude: null,
      longitude: null,
      weatherData: null
    };
  }

  componentDidMount() {
    // Fetch the user's location
    navigator.geolocation.getCurrentPosition(
      (position) => {
        const { latitude, longitude } = position.coords;
        this.setState({ latitude, longitude });

        // Fetch the weather data
        const url = `http://api.weatherstack.com/current?access_key=${API_KEY}&query=${latitude},${longitude}`;
        fetch(url)
          .then(response => response.json())
          .then(data => this.setState({ weatherData: data }))
          .catch(error => console.error(error));
      },
      (error) => {
        console.error(error);
      }
    );
  }

  static getDerivedStateFromError(error) {
    return { error: error.message };
  }

  componentDidCatch(error, info) {
    console.error(error);
    console.error(info);
  }

  render() {
    const { latitude, longitude, weatherData, error } = this.state;

    return (
      <div>
        <h1>Current Weather</h1>
        {error ? (
          <p>Something went wrong: {error}</p>
        ) : (
          <>
            {latitude && longitude && (
              <p>
                Latitude: {latitude}, Longitude: {longitude}
              </p>
            )}
            {weatherData && (
              <div>
                <p>Temperature: {weatherData.current.temperature}°C</p>
                <p>Description: {weatherData.current.weather_descriptions[0]}</p>
              </div>
            )}
          </>
        )}
      </div>
    );
  }
}

export default WeatherApp;

In the constructor, we add a new state property called error which we will use to store any errors that occur during the component’s lifecycle.

In the componentDidMount() method, we add a catch() block to handle errors when fetching the weather data. We set the error state property to the error message if an error occurs.

We also use the setState() method to set the latitude and longitude state properties when we successfully fetch the user’s location.

The static getDerivedStateFromError() method is called when an error occurs in any child component of the current component. This method should return an object to update the state of the component. In our example, we simply update the error state property with the error message.

The componentDidCatch() method is called when an error occurs in any child component of the current component and is used for logging the error to the console. In our example, we log the error and the component stack trace to the console.

Finally, in the render() method, we use the error state property to render an error message if an error occurs conditionally. Otherwise, we display the user’s location and the current weather data if they are available.

Conclusion

In conclusion, understanding and effectively implementing the React component lifecycle is essential to building efficient, scalable, and maintainable applications. As we have seen, the lifecycle methods provide developers with fine-grained control over the behavior of their components, allowing them to optimize performance, manage state, and handle errors. By leveraging the Mounting, Updating, and Unmounting methods, developers can create complex user interfaces that are both responsive and efficient.

At BairesDev, we understand the importance of leveraging the React component lifecycle to build high-quality web applications that meet our client’s needs. With our team of expert React developers, we offer custom React development services that help businesses of all sizes create innovative and impactful web applications. So if you’re looking to build an efficient and scalable web application using React, contact BairesDev today to outsource react development.

If you enjoyed this article on React, check out these these topics;

Frequently Asked Questions (FAQs)

What are the three main component lifecycle methods?

The three main component lifecycle methods in React are: Mounting, Updating, and Unmounting.

Why do we use React lifecycle methods?

We use React lifecycle methods to handle different stages of a component’s life, such as initialization, rendering, updating, and destruction, and to perform specific actions or add specific behavior during each stage.

What is the difference between React hooks and lifecycle methods?

React hooks provide a more concise way to manage state and side effects in functional components. Lifecycle methods are only available in class components and can hook into various stages of a component’s lifecycle.

Tags:
Justice Erolin

By Justice Erolin

Responsible for translating the company vision into technical roadmaps, BairesDev CTO Justice Erolin plans and coordinates engineering teams to help their output meet the highest market standards. His management and engineering expertise help take BairesDev's capabilities to the next level.

Stay up to dateBusiness, technology, and innovation insights.Written by experts. Delivered weekly.

Related articles

react-unit-testing-jest
Software Development

By BairesDev Editorial Team

15 min read

Software Development - Svelte Vs React:
Software Development

By BairesDev Editorial Team

14 min read

Contact BairesDev
By continuing to use this site, you agree to our cookie policy and privacy policy.