typescriptintermediate

React Error Boundary Component

Build a reusable error boundary with retry, fallback UI, and error reporting integration.

typescript
import { Component, type ReactNode, type ErrorInfo } from 'react';

interface Props {
  children: ReactNode;
  fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
  onError?: (error: Error, info: ErrorInfo) => void;
}

interface State {
  error: Error | null;
}

class ErrorBoundary extends Component<Props, State> {
  state: State = { error: null };

  static getDerivedStateFromError(error: Error): State {
    return { error };
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    this.props.onError?.(error, info);
  }

  reset = () => this.setState({ error: null });

  render() {
    const { error } = this.state;
    if (!error) return this.props.children;

    if (typeof this.props.fallback === 'function') {
      return this.props.fallback(error, this.reset);
    }

    return (
      this.props.fallback ?? (
        <div role="alert" style={{ padding: '2rem', textAlign: 'center' }}>
          <h2>Something went wrong</h2>
          <pre style={{ color: 'red' }}>{error.message}</pre>
          <button onClick={this.reset}>Try again</button>
        </div>
      )
    );
  }
}

// Usage
// <ErrorBoundary
//   onError={(err) => reportToSentry(err)}
//   fallback={(error, reset) => (
//     <div>
//       <p>Error: {error.message}</p>
//       <button onClick={reset}>Retry</button>
//     </div>
//   )}
// >
//   <MyComponent />
// </ErrorBoundary>

export default ErrorBoundary;

Use Cases

  • Preventing full-page crashes from component errors
  • Providing retry functionality for failed renders

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.