Error Boundaries

Catch rendering errors in a subtree and show a fallback instead of crashing.

An Error Boundary catches JavaScript errors thrown while rendering its child tree, logs them, and shows a fallback UI instead of unmounting the whole app.

Notes

  • Error boundaries are the one place React still needs a class component, using getDerivedStateFromError and componentDidCatch.
  • Most teams use the react-error-boundary package for a friendly function-based API.
  • They do not catch errors in event handlers or async code — handle those with try/catch.

Example

Example · javascript
import { Component } from 'react';

class ErrorBoundary extends Component {
  state = { hasError: false };
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  componentDidCatch(error, info) {
    console.error(error, info);
  }
  render() {
    if (this.state.hasError) return <p>Something went wrong.</p>;
    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <Widget />
    </ErrorBoundary>
  );
}

When to use it

  • A widget dashboard wraps each chart in its own error boundary so a crash in the Revenue chart shows a 'Chart unavailable' fallback without crashing the other charts.
  • A route-level error boundary catches rendering errors from any page component and shows a generic 'Something went wrong' UI instead of a blank white screen.
  • A third-party map library is wrapped in an error boundary so if the library throws during initialization the rest of the page continues to function.

More examples

Class-based error boundary

Implements the required class-based error boundary with getDerivedStateFromError and componentDidCatch.

Example · jsx
import { Component } from 'react';

class ErrorBoundary extends Component {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.error('Caught:', error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <p className="error-fallback">Something went wrong.</p>;
    }
    return this.props.children;
  }
}

Wrap a widget in a boundary

Gives each chart widget its own error boundary so a crash in one does not affect the other.

Example · jsx
import ErrorBoundary from './ErrorBoundary';
import RevenueChart from './RevenueChart';

function Dashboard() {
  return (
    <div className="dashboard">
      <ErrorBoundary>
        <RevenueChart />
      </ErrorBoundary>
      <ErrorBoundary>
        <UsersChart />
      </ErrorBoundary>
    </div>
  );
}

Error boundary with reset

Adds a Retry button that increments a key to force React to remount the child tree, clearing the error.

Example · jsx
import { Component } from 'react';

class RetryBoundary extends Component {
  state = { hasError: false, key: 0 };

  static getDerivedStateFromError() { return { hasError: true }; }

  retry = () => this.setState(s => ({ hasError: false, key: s.key + 1 }));

  render() {
    if (this.state.hasError) {
      return (
        <>
          <p>Failed to load.</p>
          <button onClick={this.retry}>Try again</button>
        </>
      );
    }
    return <div key={this.state.key}>{this.props.children}</div>;
  }
}

Discussion

  • Be the first to comment on this lesson.