React Error Boundaries

Catch and isolate unexpected runtime JavaScript crashes gracefully using declarative React error boundaries.

TL;DR

  1. Catch unexpected rendering exceptions gracefully using error boundaries.
  2. Display user-friendly fallback interfaces instead of unmounting blank screens.
  3. Isolate crashes to individual widgets without destroying entire application trees.

Class-Based Error Boundary

    Derived State From Error

    Update component state when render exception occurs.

    static getDerivedStateFromError(error: Error) {
      return { hasError: true, error };
    }
    Component Did Catch

    Report stack trace to telemetry service.

    componentDidCatch(
      error: Error,
      info: React.ErrorInfo
    ) {
      reportErrorToService(error, info.componentStack);
    }
    Conditional Render Guard

    Render fallback UI if error flag active.

    if (this.state.hasError) {
      return <FallbackCard error={this.state.error} />;
    }
    return this.props.children;

Using react-error-boundary

    Declarative Boundary

    Wrap unstable components with functional boundary.

    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onReset={() => console.log('Resetting')}
    >
      <UnstableComponent />
    </ErrorBoundary>
    Fallback Component Props

    Access error details and reset callback.

    export function ErrorFallback({
      error,
      resetErrorBoundary,
    }: FallbackProps) {
      return (
        <CardView>
          <CardTitle>Error Occurred</CardTitle>
          <Text>{error.message}</Text>
          <Button onClick={resetErrorBoundary}>
            Retry
          </Button>
        </CardView>
      );
    }
    Reset Keys Trigger

    Auto-reset boundary when query parameters change.

    <ErrorBoundary
      resetKeys={[selectedUserId]}
      FallbackComponent={ErrorFallback}
    >
      <UserProfile id={selectedUserId} />
    </ErrorBoundary>

Error Recovery Strategies

    Clear Cache on Reset

    Purge stale cache keys when retrying failed component.

    const onReset = () => {
      queryClient.resetQueries();
    };
    Navigation Fallback Button

    Provide route back to safety from error screen.

    export function FallbackActions() {
      return (
        <Button onClick={() => navigate('/')}>
          Return Home
        </Button>
      );
    }
    Granular Widget Reset

    Reset only affected editor without reloading page.

    <ErrorBoundary onReset={resetDraft}>
      <CommentEditor />
    </ErrorBoundary>

Error Boundary Boundaries

    Widget-Level Isolation

    Prevent individual chart failures from crashing app.

    <DashboardShell>
      <ErrorBoundary FallbackComponent={WidgetFallback}>
        <StockChart />
      </ErrorBoundary>
    </DashboardShell>
    Uncaught Errors Fallback

    Catch errors that escape all inner boundaries.

    // Root boundary for catastrophic failures
    <RootErrorBoundary>
      <App />
    </RootErrorBoundary>
    Async Error Bridge

    Forward async errors into boundary with useErrorBoundary.

    const { showBoundary } = useErrorBoundary();
    useEffect(() => {
      apiCall().catch(showBoundary);
    }, []);

Tips

  1. Place strategic error boundaries like <ErrorBoundary> around independent features like feeds or comments so an error leaves the rest functional.
  2. Always log captured errors and component stack traces to production monitoring services like Sentry inside componentDidCatch.

Warnings

  1. Error boundaries do not catch errors inside asynchronous timers, network fetch callbacks, or native DOM event handlers.
  2. Failing to provide a recovery reset mechanism leaves users trapped on error fallback screens until they perform a hard page refresh.

In Practice

FAQ