Chapter 4 of 4
Boundaries with Suspense
Combining loading and error states into one predictable shell.
Loading and failure are two outcomes of the same operation, so their boundaries usually sit together. The error boundary goes outside, because a chunk that fails to download throws rather than suspends.
<ErrorBoundary fallback={<p>Could not load the report.</p>}>
<Suspense fallback={<ReportSkeleton />}>
<Report id={reportId} />
</Suspense>
</ErrorBoundary>Resetting on retry
import { ErrorBoundary } from "react-error-boundary";
function Section({ id }) {
return (
<ErrorBoundary
resetKeys={[id]} // clears the error when id changes
fallbackRender={({ resetErrorBoundary }) => (
<div role="alert">
<p>Could not load this section.</p>
<button onClick={resetErrorBoundary}>Retry</button>
</div>
)}
>
<Suspense fallback={<Skeleton />}>
<Content id={id} />
</Suspense>
</ErrorBoundary>
);
}A checklist for production
- A root boundary so nothing ever renders a blank page.
- A boundary per route and per independent widget.
- Simple fallbacks that cannot themselves throw.
- A retry path, and reset keys so navigation clears stale errors.
componentDidCatchwired to your monitoring service with the component stack.try/catchin handlers and.catch(setError)for async work, since boundaries never see those.