React Error Boundaries in Production: Best Practices
What are React Error Boundaries?
A React Error Boundary is a React component that catches JavaScript errors anywhere in its child component tree, logs those errors, and displays a fallback UI instead of crashing the entire component tree (which typically results in a blank "white screen of death"). Introduced in React 16, they act similarly to a catch {} block but for React components, ensuring that an error in a minor UI element doesn't take down the entire application.
React error boundaries are your first line of defense against front-end crashes. When an unexpected error occurs during rendering, lifecycle methods, or in the constructors of any child component, the error boundary catches it. Without them, a single undefined variable in a deeply nested component can cause the entire React tree to unmount, leaving the user staring at a blank page.
In production, putting a single error boundary at the very top of your app is a rookie mistake. You must implement them per route or section and always report the error with the component stack and route context.
The Production-Ready Pattern
A basic error boundary is simple, but a production-ready one requires state management for recovery and robust logging capabilities.
import React from 'react';
class Boundary extends React.Component {
state = { hasError: false, errorId: null }
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// Generate a unique ID for this error occurrence
const errorId = crypto.randomUUID();
this.setState({ errorId });
// Send error + info.componentStack + route to your tracker
// In a real app, this goes to Relia, Sentry, Datadog, etc.
console.error("Caught by boundary:", error, info.componentStack);
// Example: sendToTracker(error, info, { route: window.location.pathname, errorId });
}
render() {
if (this.state.hasError) {
return (
<div className="error-fallback-container">
<h2>Something went wrong in this section.</h2>
<p>Error Reference: {this.state.errorId}</p>
<button onClick={() => this.setState({hasError:false})}>
Try Again
</button>
</div>
);
}
return this.props.children;
}
}
export default Boundary;
Granular Wrapping is Crucial
Wrap your checkout, dashboard, settings, and navigation components separately. If a third-party widget in the sidebar crashes, the main content area (where the user is actually reading or buying) should remain fully functional. Granularity isolates failures, which is a core tenet of building resilient web applications.
What Error Boundaries Don't Catch
It's critical to understand the limitations of Error Boundaries. They do not catch errors for:
- Event Handlers: A crash inside an
onClickoronSubmithandler will not trigger the boundary. React knows the event failed, but the component tree is still intact. You needtry/catchblocks or globalwindow.onerrorlisteners. - Asynchronous Code:
setTimeout,requestAnimationFrame, or API fetch promises. Unhandled promise rejections require a globalunhandledrejectionevent listener (see our guide on /blog/unhandled-promise-rejection-nodejs-fix for similar concepts). - Server-Side Rendering (SSR): Errors on the server must be handled by the server framework.
- Hydration Mismatches: If the server renders different HTML than the client expects, React logs a warning, but it doesn't trigger the boundary in the same way a runtime crash does.
To fully protect your app, Error Boundaries must be part of a broader observability strategy, addressing /blog/silent-frontend-failures-user-churn.
The Ultimate Autonomous Fix: Relia
Catching the error is only half the battle; fixing it is where the real cost lies. This is where Relia steps in as the ultimate autonomous bug fixing tool.
When your Error Boundary catches a crash, Relia doesn't just send you a stack trace. The captured crash arrives in your dashboard with a proposed code patch. Relia's AI analyzes the component stack, the surrounding code context, and the exact state that caused the crash, generating a ready-to-merge PR in minutes. You go from a user seeing a fallback UI to a deployed fix before they even have a chance to complain.
FAQ
Do I need Sentry for React errors?
Any tracker works if it captures component stack + user actions. Replay helps for invalid-state bugs. Relia goes one step further — the captured crash arrives with a proposed code patch, not just a replay to watch.
How do I avoid noise?
Ignore extension errors and ResizeObserver loops. Keep 100% of checkout/payment errors.
What is a good fallback UI?
Section-level retry + "report issue" that attaches session ID. Never full-page blank.
