ErrorBoundary
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/error-boundary.jsonWhat it catches is narrower than products expect. It catches errors thrown while rendering, below itself. It does not catch:
- a failed fetch — that is a value a component receives and shows, which is QueryState;
- an error in an event handler — nothing catches those but the handler;
- anything thrown after the render, in a timer or a promise.
So this is the last line: something that should never have thrown did, and the alternative is a white page with the product’s name at the top.
<ErrorBoundary resetKey={route} onError={report} labels={{ title: 'Something went wrong', body: '…', details: 'Details', retry: 'Try again' }}> <Screen /></ErrorBoundary>A class component, and the only one in the set. Not a style choice: React
gives no hook for catching a render error, and componentDidCatch exists
nowhere else.
resetKey is what un-crashes it. Without one, a boundary that has caught
once stays caught — the reader navigates away from the broken screen and the
crash follows them, because nothing told the boundary the reason had gone. Pass
the route.
It clears on a changed key rather than on any re-render: resetting whenever the parent renders re-runs the throwing child at once, and the screen flickers between the crash and the fallback for as long as the cause is there.
The message is kept, and folded away. The reader cannot fix it, but the
reader is who files it — and a screen that hides the one string worth quoting
turns a bug report into a guess. It sits inside a closed <details>, because
it is evidence rather than an instruction.
labels is required. They are the only text here, and English inside a
primitive is text no product can translate.
Props
Read from the types in ui/error-boundary.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.
| Prop | Type | Default | |
|---|---|---|---|
childrenrequired | ReactNode | ||
fallback | (error: Error, reset: () => void) => ReactNode | Draw something else instead of the default screen. | |
resetKey | unknown | Change this to clear the error - a route, usually. | |
onError | (error: Error, info: ErrorInfo) => void | Somewhere to send it. The product owns whether that is a log, a file or a service - the boundary only knows it happened. | |
labelsrequired | ErrorBoundaryLabels | The words on the default screen. Required, and not defaulted: they are the only text here, and English inside a primitive is text no product can translate. |
Accessibility
The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 6 rules applied and passed, and none failed. The accessibility report has every item.
History
Each release that changed ui/error-boundary.tsx - the file a product copies - newest first.