Error boundaries are a containment tool
An error boundary catches rendering errors in descendant components, displays a fallback, and lets the rest of the interface continue. It is not a substitute for validating API responses or handling failed requests, but it is an essential last line of defence for the rendering layer.
Catch
Unexpected render-time failures in a subtree, such as a visualization or rich editor.
Preserve
Navigation, stable content, and the user's ability to move to another part of the product.
Recover
A retry button, a reset on route change, or a safe route back to a known-good screen.
Learn
A structured error event with release, route, user-safe context, and a component stack.
Place boundaries around meaningful user tasks
One boundary around the whole app is better than a white screen, but it offers poor recovery. Use a small number of boundaries around independent, valuable regions: a payment step, an analytics panel, a rich preview, or an integration widget. A failure there should not remove the header, navigation, or previously loaded account information.
// components/AccountDashboard.js
<ErrorBoundary onError={reportUiError}>
<RevenueChart accountId={accountId} />
</ErrorBoundary>
// Keep the account summary and navigation outside this boundary.
// The chart can fail independently without turning the dashboard blank.Keep fallbacks specific. A chart can say that chart data is unavailable and offer a retry; a checkout failure should preserve the cart and offer support. Generic “something went wrong” copy is acceptable only at the application shell, where the exact broken feature is unknown.
Handle asynchronous failures before they reach rendering
Requests, mutations, and event handlers need explicit loading, error, and retry states. Normalize the API response at the edge, distinguish an expected validation issue from a transient upstream failure, and avoid rendering data until its required fields are present.
async function saveProfile(input) {
try {
const response = await fetch("/api/profile", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(input),
});
if (!response.ok) throw new Error("Profile update failed");
return await response.json();
} catch (error) {
// Show a local message and report safe diagnostic context.
reportUiError(error, { action: "save_profile" });
throw error;
}
}Pair this approach with good input validation and authorization in your API routes. OurNext.js authentication and RBAC guideexplains how to keep sensitive operations behind a trustworthy server boundary.
Make recovery intentional and observable
Retrying the same broken render without changing any input can create a frustrating loop. Reset a boundary when its route or record identifier changes, let users retry a transient request, and provide an escape route when the feature cannot recover. Never discard form input or cart state merely because an unrelated widget failed.
Example fallback characteristics
- Plain-language explanation of what is unavailable
- A focused retry that does not reload unrelated page state
- A safe link back to the previous stable task
- A support reference or request ID when the issue persists
Report exceptions with the route, release identifier, browser information, component stack, and a correlation ID—not passwords, tokens, form bodies, or payment details. Combine those events with performance and uptime signals using a practical production observability checklist.
React production-recovery checklist
✓ A top-level boundary prevents a permanent blank screen
✓ Independent tasks have focused boundaries and fallbacks
✓ API reads and writes expose loading, error, and retry states
✓ Fallbacks preserve unaffected content and user input
✓ Route or record changes reset stale error state safely
✓ Errors include release and route context, never secrets
✓ Monitoring alerts distinguish user-impacting failures
✓ Failure paths are exercised in staging and release QA
Build a more resilient React application
Endurance Softwares helps teams build React, Next.js, and Node.js applications with reliable UI recovery, secure APIs, practical monitoring, and maintainable delivery workflows.