React Error Boundaries in 2025
Graceful error handling in React. What error boundaries are, how to use them, and patterns that work.
The Problem
A JavaScript error in one component crashes your whole app.
function BrokenComponent() {
throw new Error("Oops!");
}
// Whole app dies
function App() {
return (
<div>
<Header />
<BrokenComponent /> {/* 💥 */}
<Footer />
</div>
);
}
Error Boundaries
Class components that catch errors in their children:
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
// Log to error reporting service
console.error("Error caught:", error, info);
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
Yes, it has to be a class component. That's the API.
Using It
Wrap parts of your app:
function App() {
return (
<div>
<Header />
<ErrorBoundary fallback={<p>Something went wrong</p>}>
<MainContent />
</ErrorBoundary>
<Footer />
</div>
);
}
Now an error in MainContent shows the fallback instead of crashing everything.
react-error-boundary Package
The react-error-boundary package makes this easier:
npm install react-error-boundary
import { ErrorBoundary } from "react-error-boundary";
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<p>Something went wrong:</p>
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
function App() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onError={(error, info) => logErrorToService(error, info)}
onReset={() => {
// Reset app state here
}}
>
<MainContent />
</ErrorBoundary>
);
}
Granular Boundaries
Don't wrap your whole app in one boundary. Be surgical:
function Dashboard() {
return (
<div>
<ErrorBoundary fallback={<WidgetError />}>
<UserWidget />
</ErrorBoundary>
<ErrorBoundary fallback={<WidgetError />}>
<StatsWidget />
</ErrorBoundary>
<ErrorBoundary fallback={<WidgetError />}>
<ChartWidget />
</ErrorBoundary>
</div>
);
}
One widget crashing doesn't take down the others.
Limitations
Error boundaries DON'T catch:
- Event handlers (use try/catch)
- Async code (use try/catch)
- Server-side rendering errors
- Errors in the boundary itself
They only catch errors during rendering, lifecycle methods, and constructors.
The Pattern
1. Add boundaries around isolated features 2. Show meaningful fallbacks 3. Log errors for debugging 4. Provide recovery options (retry buttons)
Your users will encounter errors. Make sure it doesn't ruin their day.