Technology · React

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.

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.

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

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

React Conditional RenderingReact Forms Handling