ReactJS - static getDerivedStateFromError() Method



When a component or its children encounter an error while rendering in React, it can be difficult to handle and communicate that error to users. The getDerivedStateFromError function comes into action here. In this tutorial, we will see how it works.

In React, we can define a particular function called getDerivedStateFromError in our class components. When a child component, no matter how deep in the hierarchy it is, encounters an error, React will invoke this function. Instead of displaying a blank or broken user interface, we can display a detailed error message.

Syntax

static getDerivedStateFromError(error)

Parameters

error − The error parameter in getDerivedStateFromError provides error information. It is normally an Error instance, but it can be of another type.

Return Value

The method should return the updated state, showing that the component should display the error message.

Examples

Example 1

Creating a basic React app that uses the getDerivedStateFromError function requires creating a simple class component with error limits. Below is a small example using the getDerivedStateFromError() function −

import React, { Component } from 'react';

class ErrorBoundary extends Component {
   constructor(props) {
      super(props);
      this.state = { hasError: false, errorMessage: '' };
   }   
   static getDerivedStateFromError(error) {
      return { hasError: true, errorMessage: error.message };
   }   
   componentDidCatch(error, errorInfo) {
      // Log the error here
      console.error(error, errorInfo);
   }   
   render() {
   if (this.state.hasError) {
      return (
         <div>
            <h2>Something went wrong</h2>
            <p>{this.state.errorMessage}</p>
         </div>
      );
   }   
   return this.props.children;
   }
}

class App extends Component {
   render() {
      return (
         <div>
            <h1>Simple Error Handling App</h1>
            <ErrorBoundary>
               {/* error in a child component */}
               <ChildComponent />
            </ErrorBoundary>
         </div>
      );
   }
}
class ChildComponent extends Component {
   componentDidMount() {
      // Simulate an error
      throw new Error('Error in ChildComponent');
   }
   
   render() {
      return <p>This is a child component</p>;
   }
}

export default App;

Output

simple error handling app

This example shows how to make a simple React app with an ErrorBoundary class component that uses getDerivedStateFromError and componentDidCatch functions. To show error handling, the ChildComponent knowingly throws an error in its componentDidMount lifecycle function.

When we launch the app, we will receive an error message in the user interface. We can modify and expand this code to meet our own requirements.

Example 2

Here is another example with the help of getDerivedStateFromError function in a React component for error handling. This time, we will simulate an error in a child component that renders an image −

import React, { Component } from 'react';
import './App.css';

class ErrorBoundary extends Component {
   constructor(props) {
      super(props);
      this.state = { hasError: false, errorMessage: '' };
   }   
   static getDerivedStateFromError(error) {
      return { hasError: true, errorMessage: error.message };
   }   
   componentDidCatch(error, errorInfo) {
      // Log the error here
      console.error(error, errorInfo);
   }   
   render() {
   if (this.state.hasError) {
      return (
         <div>
            <h2>Something went wrong</h2>
            <p>{this.state.errorMessage}</p>
         </div>
      );
   }
   
   return this.props.children;
   }
}
class App extends Component {
   render() {
      return (
         <div className='App'>
            <h1>Error Handling with Images</h1>
            <ErrorBoundary>
               {/* error in a child component */}
               <ImageComponent />
            </ErrorBoundary>
         </div>
      );
   }
}
class ImageComponent extends Component {
   state = {
      hasError: false,
   };
   
   // Error occur by attempting to load an invalid image
   loadImage = () => {
      const img = new Image();
      img.src = 'image-url1';
      img.onload = () => {
         // This will not execute because the image source is invalid
      };
      img.onerror = () => {
         // Error and catch it in the ErrorBoundary
         this.setState({ hasError: true });
      };
   };   
   componentDidMount() {
      this.loadImage();
   }
   
   render() {
      if (this.state.hasError) {
         // Render an alternative content when an error occurs
         return <p>Failed to load the image</p>;
      }
      
      return <img src="image-url2" alt="A Valid Image" />;
   }
}

export default App;

Output

error handling with images

In this example, ImageComponent component attempts to load an image with an invalid URL, which triggers an error. The ErrorBoundary catches the error, and we can customize the rendering of the component when an error occurs.

Example 3

In this example, we'll create a bug in a child component that gets data from an API. The getDerivedStateFromError function will be used to manage the error and show a user-friendly message. The code is as follows −

import React, { Component } from 'react';
import './App.css';

class ErrorBoundary extends Component {
   constructor(props) {
      super(props);
      this.state = { hasError: false, errorMessage: '' };
   }   
   static getDerivedStateFromError(error) {
      return { hasError: true, errorMessage: error.message };
   }   
   componentDidCatch(error, errorInfo) {
      // Log the error here
      console.error(error, errorInfo);
   }   
   render() {
      if (this.state.hasError) {
         return (
            <div>
               <h2>Something went wrong</h2>
               <p>{this.state.errorMessage}</p>
            </div>
         );
      }
      
      return this.props.children;
   }
}
class App extends Component {
   render() {
      return (
         <div>
            <h1>Error Handling with API Fetch</h1>
            <ErrorBoundary>
               {/* error in a child component */}
               <ApiDataComponent />
            </ErrorBoundary>
         </div>
      );
   }
}
class ApiDataComponent extends Component {
   state = {
      data: null,
   };
   
   componentDidMount() {
      // Error by trying to fetch data from an invalid API endpoint
      fetch('https://invalid-api-endpoint')
      .then((response) => response.json())
      .then((data) => this.setState({ data }))
      .catch((error) => {
      // Error and catch it in the ErrorBoundary
      throw new Error('Error fetching data from the API');
      });
   }
   
   render() {
      return (
         <div className='App'>
            <h3>API Data</h3>
            {this.state.data ? (
               <ul>
               {this.state.data.map((item) => (
                  <li key={item.id}>{item.name}</li>
               ))}
               </ul>
               ) : (
               <p>Loading data...</p>
            )}
         </div>
      );
   }
}

export default App;

Output

error handling with api fetch

Limitations

  • getDerivedStateFromError should be a pure function with no side effects. If we have to perform activities such as calling an analytics service, we should also use componentDidCatch.

  • There is no direct equivalent for getDerivedStateFromError when working with function components. To provide similar functionality, we can construct a single ErrorBoundary component or use a package like react-error-boundary.

Summary

Understanding getDerivedStateFromError is critical for properly managing mistakes in React apps. You can give a better user experience by displaying helpful error messages instead of perplexing UI issues if you incorporate this method into your error-handling strategy.

reactjs_reference_api.htm
Advertisements