Error Boundaries and Building Resilient UI in React
A practical guide to Error Boundaries in React, why they exist, and how to build failure‑resistant user interfaces.
Error Boundaries and Building Resilient UI in React
Runtime errors in React can break entire component trees and leave the user staring at a blank screen. Error Boundaries provide a structured way to catch unexpected failures and keep your UI functional, isolated, and recoverable.
This guide explains exactly how Error Boundaries work, when to use them, and how to design resilient UX patterns around them.
1. What Error Boundaries Solve
React error boundaries catch errors in:
- rendering
- lifecycle methods
- constructors of child components
They do not catch:
- event handlers
- async errors
- server components
- errors thrown inside
useEffect
Example of an uncaught error:
function Profile({ user }) {
if (!user) throw new Error("User not found");
return <h1>{user.name}</h1>;
}Without a boundary, the entire React tree may unmount.
Error Boundaries prevent that by isolating failure to a specific subtree.
2. Creating an Error Boundary
Error boundaries must be class components.
import React from "react";
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error("Error boundary caught:", error, info);
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}Usage:
<ErrorBoundary>
<CommentsSection />
</ErrorBoundary>3. Designing the Fallback UI
Great fallback UI is:
- helpful
- branded
- actionable
Example:
function FallbackUI() {
return (
<div className="p-4 border rounded">
<h2>Something went wrong</h2>
<button onClick={() => window.location.reload()}>
Reload Page
</button>
</div>
);
}For dashboards, you might show:
- retry button
- support link
- partial UI
- cached data
4. Combining Error Boundaries with Suspense
Error Boundaries and Suspense complement each other.
<ErrorBoundary fallback={<Err />}>
<Suspense fallback={<Loading />}>
<UserProfile />
</Suspense>
</ErrorBoundary>Suspense handles loading.
Error boundaries handle failure.
5. Component Level vs Application Level Boundaries
App-Level Boundary
Protects the entire UI from catastrophic failures.
Feature-Level Boundary
Wrap unstable or API-heavy sections:
<ErrorBoundary>
<ExpensiveChart />
</ErrorBoundary>Micro-Boundaries
Useful around:
- third-party components
- charts
- maps
- rich text editors
6. Logging and Monitoring
Inside componentDidCatch, send the error to:
- Sentry
- Datadog
- LogRocket
componentDidCatch(error, info) {
sendToMonitoringService({
error,
componentStack: info.componentStack,
});
}Resilient UIs always include monitoring hooks.
7. Common Mistakes
Mistake 1: Relying on boundaries to catch async errors
This will not work:
useEffect(() => {
throw new Error("Not caught by boundary");
}, []);Async errors need:
- try/catch
query.onErrorin React Query- global error listeners
Mistake 2: Wrapping entire pages unnecessarily
Boundaries should be targeted.
Too many boundaries hide errors that should be fixed.
Mistake 3: No fallback UI strategy
A blank screen is not acceptable for production.
Good fallback = good UX.
8. Error Recoverability
Error boundaries can reset state:
<ErrorBoundary key={userId}>
<UserProfile id={userId} />
</ErrorBoundary>Changing the key remounts the subtree.
Final Thoughts
Error boundaries are not just a React feature but an architectural requirement for resilient systems. With proper placement, helpful fallback UIs, and integrated monitoring, they protect your application from unexpected runtime failures and keep the user experience intact.