React Error Boundaries
What Are Error Boundaries?
Error Boundaries are class components that catch JavaScript errors in child components during rendering, lifecycle methods, and constructors — displaying fallback UI instead of crashing the app.
Two lifecycle methods:
static getDerivedStateFromError(error)— update state during render phase (pure, no side effects)componentDidCatch(error, info)— log errors during commit phase (allows side effects)
Basic Implementation
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
// Log to error monitoring service
errorMonitoring.report(error, {
componentStack: info.componentStack,
userId: getCurrentUser()?.id
});
}
render() {
if (this.state.hasError) {
return (
<div role="alert">
<h2>Something went wrong</h2>
<p>{this.state.error.message}</p>
<button onClick={() => this.setState({ hasError: false, error: null })}>
Try again
</button>
</div>
);
}
return this.props.children;
}
}
What Error Boundaries DON'T Catch
- Event handlers — use try/catch instead
- Async code — setTimeout, Promises
- SSR errors
- Errors in the boundary itself
Strategic Placement
// 1. Root-level: catch catastrophic failures
function App() {
return (
<ErrorBoundary fallback={<CrashPage />}>
<Router />
</ErrorBoundary>
);
}
// 2. Route-level: isolate pages from each other
function Router() {
return (
<Routes>
<Route path="/dashboard" element={
<ErrorBoundary fallback={<PageError />}>
<Dashboard />
</ErrorBoundary>
} />
</Routes>
);
}
// 3. Feature-level: graceful degradation
function ProductPage() {
return (
<div>
<ProductDetails /> {/* Critical */}
<ErrorBoundary fallback={<p>Reviews unavailable</p>}>
<ReviewSection /> {/* Non-critical */}
</ErrorBoundary>
</div>
);
}
React 18 + Suspense Integration
<ErrorBoundary fallback={<ErrorUI />}>
<Suspense fallback={<Loading />}>
<AsyncComponent />
</Suspense>
</ErrorBoundary>
This handles three states:
- Loading — Suspense shows skeleton
- Error — ErrorBoundary shows error UI
- Success — component renders
Streaming SSR
With React 18's streaming SSR, errors in one component don't break the entire stream:
// Server renders partial page even if one section errors
<ErrorBoundary fallback={<SectionError />}>
<Suspense fallback={<Skeleton />}>
<SlowDataSection /> {/* Can error without breaking other sections */}
</Suspense>
</ErrorBoundary>
Auto-Reset on Navigation
function RouteErrorBoundary({ children }) {
const location = useLocation();
return (
<ErrorBoundary
key={location.pathname} // New key = resets error state on navigation
fallback={<PageError />}
>
{children}
</ErrorBoundary>
);
}
Using react-error-boundary Library
import { ErrorBoundary } from 'react-error-boundary';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div>
<p>Error: {error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
<ErrorBoundary
FallbackComponent={ErrorFallback}
onError={(error, info) => logError(error, info)}
onReset={() => window.location.reload()}
>
<Dashboard />
</ErrorBoundary>
Content from Frontend-Master-Prep-Series — 03-react