What is Error Boundaries in React?

React Error Boundaries are a crucial feature designed to catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback user interface instead of allowing the entire application to crash. This article provides a clear, direct guide on how Error Boundaries work, how to implement them in your code, and the specific scenarios where they are most effective.

Understanding Error Boundaries

In standard JavaScript, a runtime error inside a component can break the application’s state and cause React to unmount the entire component tree, leaving users with a blank white screen. Error Boundaries solve this problem by acting like a Java or C# try-catch block, but specifically tailored for React components.

An Error Boundary is a React component that wraps around other components. If any child component throws an error during rendering, in a lifecycle method, or in a constructor, the Error Boundary catches it and prevents it from propagating upward.

How to Implement an Error Boundary

To create an Error Boundary, you must use a class component. Currently, React does not support functional components as Error Boundaries directly because the required lifecycle methods do not have functional equivalents.

An Error Boundary class component relies on one or both of the following lifecycle methods:

  1. static getDerivedStateFromError(error): This method renders a fallback UI after an error has been thrown. It receives the error as a parameter and returns an updated state object.
  2. componentDidCatch(error, errorInfo): This method is used to perform side effects, such as logging the error to an external error reporting service (e.g., Sentry or LogRocket).

Basic Implementation Example

import React, { Component } from 'react';

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

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // You can log the error to an error reporting service
    console.error("ErrorBoundary caught an error", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong. Please try again later.</h1>;
    }

    return this.props.children; 
  }
}

export default ErrorBoundary;

To use this boundary, wrap it around any component that might throw an error:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

What Error Boundaries Do Not Catch

While Error Boundaries are highly effective, they do not catch errors in every situation. You must handle errors manually using traditional try-catch blocks in the following scenarios:

Best Practices for Placement

You can choose the granularity of your Error Boundaries based on your application’s user experience needs: