React Error Boundaries

Catch React errors with error boundaries, handle lifecycle errors, and display fallback UI gracefully.

TL;DR

  1. 01Create a class component with getDerivedStateFromError to catch errors.
  2. 02Display fallback UI when errors are caught instead of a blank page.
  3. 03Log errors for debugging and monitoring in production.

Tips

  1. 01Use error boundaries at the page level and around features to keep the rest of your app working when something breaks.

Warnings

  1. 01Error boundaries only catch errors during rendering, not in event handlers or async code — use try-catch for those.

Creating Error Boundaries

  • Create a class component with error lifecycle methods.
    class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
      
      static getDerivedStateFromError(error) {
        return { hasError: true };
      }
      
      render() {
        if (this.state.hasError) {
          return <h1>Something went wrong.</h1>;
        }
        return this.props.children;
      }
    }
  • Error boundaries only work with class components, not functions.
  • Use getDerivedStateFromError to update state when an error occurs.
  • This catches errors in the component tree below the boundary.
  • Error boundaries must return a fallback UI or null.

Logging and Debugging

  • Use componentDidCatch to log errors for debugging.
    class ErrorBoundary extends React.Component {
      componentDidCatch(error, errorInfo) {
        console.error("Error caught:", error);
        console.error("Error info:", errorInfo.componentStack);
        
        // Send to error tracking service
        logErrorToService(error, errorInfo);
      }
      
      render() {
        if (this.state.hasError) {
          return <h1>Something went wrong</h1>;
        }
        return this.props.children;
      }
    }
  • componentDidCatch is called after an error has been thrown.
  • Use it to log errors to services like Sentry or DataDog.
  • Include the error stack and component tree information in logs.
  • Never throw errors from componentDidCatch itself.

What Error Boundaries Catch

  • Error boundaries catch errors during rendering in child components.
    // This error is caught
    function Child() {
      throw new Error("Oops");
    }
    
    <ErrorBoundary>
      <Child /> {/* Error is caught here */}
    </ErrorBoundary>
  • They do NOT catch errors from event handlers or async code.
    // This error is NOT caught
    <button onClick={() => {
      throw new Error("Oops");
    }}>
      Click me
    </button>
    
    // Use try-catch for these instead
    <button onClick={() => {
      try {
        riskyOperation();
      } catch (error) {
        // Handle error
      }
    }}>
      Safe click
    </button>
  • Error boundaries don't catch errors in the boundary itself.

Nested Error Boundaries

  • Use multiple error boundaries to granularly handle errors.
    <ErrorBoundary>
      <Header />
      <ErrorBoundary>
        <MainContent />
      </ErrorBoundary>
      <Sidebar />
    </ErrorBoundary>
  • Errors in MainContent are caught by the inner boundary.
  • Errors in Header or Sidebar are caught by the outer boundary.
  • This lets you keep the rest of the app running when part fails.
  • Use granular boundaries for user-facing features like widgets.

Error Boundary Patterns

  • Show a user-friendly error message with recovery option.
    class ErrorBoundary extends React.Component {
      render() {
        if (this.state.hasError) {
          return (
            <div>
              <h1>Oops, something went wrong</h1>
              <p>Please try refreshing the page</p>
              <button onClick={() => window.location.reload()}>
                Reload Page
              </button>
            </div>
          );
        }
        return this.props.children;
      }
    }
  • Create reusable error boundary components for common layouts.
    <PageErrorBoundary>
      <PageContent />
    </PageErrorBoundary>
  • Combine error boundaries with error tracking for production monitoring.
  • Reset error state when user navigates to a new page.

FAQ