Error Boundary is a React component that catches JavaScript errors in its child component tree during rendering, lifecycle methods, and constructors — and displays a fallback UI instead of crashing the entire application.
Think of it like a try-catch block for your UI — if one component crashes, the error boundary catches it and shows a friendly error message, while the rest of the app continues working.
Complete implementation:
1import React, { Component, ErrorInfo, ReactNode } from "react";23interface Props {4 children: ReactNode;5 fallback?: ReactNode;6 onError?: (error: Error, info: ErrorInfo) => void;7}89interface State {10 hasError: boolean;11 error: Error | null;12}1314class ErrorBoundary extends Component<Props, State> {15 state: State = { hasError: false, error: null };1617 static getDerivedStateFromError(error: Error): State {18 // Update state so the next render shows fallback UI19 return { hasError: true, error };20 }2122 componentDidCatch(error: Error, info: ErrorInfo) {23 // Log error to monitoring service24 console.error("Error caught:", error, info.componentStack);25 this.props.onError?.(error, info);26 }2728 render() {29 if (this.state.hasError) {30 return (31 this.props.fallback || (32 <div style={{ padding: "20px", textAlign: "center" }}>33 <h2>Something went wrong</h2>34 <p>{this.state.error?.message}</p>35 <button onClick={() => this.setState({ hasError: false, error: null })}>36 Try again37 </button>38 </div>39 )40 );41 }42 return this.props.children;43 }44}4546// Usage47function App() {48 return (49 <ErrorBoundary50 fallback={<div>Something broke! Please refresh.</div>}51 onError={(error, info) => {52 // Send to Sentry, LogRocket, etc.53 reportError(error, info.componentStack);54 }}55 >56 <Dashboard />57 </ErrorBoundary>58 );59}
What it catches:
What it does NOT catch:
Error handling for event handlers:
1function Button() {2 const handleClick = () => {3 try {4 riskyOperation();5 } catch (error) {6 // Handle error manually7 console.error("Button click error:", error);8 }9 };10 return <button onClick={handleClick}>Click me</button>;11}
Best practices: