Runnable lesson · press Try it on the examples to edit and run them here.
If a component throws an error while rendering, React removes the whole component tree from the screen and the user sees a blank page. An error boundary is a component that catches errors in its children and shows a fallback UI instead, so one broken part does not take down the entire app.
Error boundaries are class components
Error boundaries are the one remaining place where you need a class component. React has no hook for it. You write one class and reuse it everywhere:
class ErrorBoundary extends React.Component {
state = { error: null };
// 1. Update state so the next render shows the fallback
static getDerivedStateFromError(error) {
return { error };
}
// 2. Log the error (send it to an error-tracking service in production)
componentDidCatch(error, info) {
console.log("Logged:", error.message, info.componentStack ? "(has component stack)" : "");
}
reset = () => {
this.props.onReset?.(); // let the parent fix the cause
this.setState({ error: null }); // then try rendering the children again
};
render() {
if (this.state.error) {
return (
<div role="alert">
<p>Something went wrong in this section.</p>
<button onClick={this.reset}>Try again</button>
</div>
);
}
return this.props.children;
}
}
function Bomb({ explode }) {
if (explode) throw new Error("Boom");
return <p>Everything is fine</p>;
}
function App() {
const [explode, setExplode] = React.useState(false);
return (
<div>
<p>Safe area</p>
<ErrorBoundary onReset={() => setExplode(false)}>
<Bomb explode={explode} />
</ErrorBoundary>
<button onClick={() => setExplode(true)}>Break it</button>
</div>
);
}
The boundary shows its fallback when Bomb throws, and the rest of the page (the “Safe area” text and the button) keeps working. Try again calls onReset so the parent removes the cause (explode back to false) and then clears the error so the children render again. Without fixing the cause, the same error would simply happen again.
The two special methods:
static getDerivedStateFromError(error)runs while React is rendering and returns new state. Use it to decide what to show.componentDidCatch(error, info)runs after the error is committed. Use it for side effects such as logging.info.componentStacksays which components were involved.
What error boundaries catch
They catch errors thrown:
- while rendering their children,
- in lifecycle methods and constructors of their children,
- in hooks in children.
What they do not catch
- Event handlers. An error in
onClickdoes not break rendering. Usetry/catchinside the handler and set error state. - Asynchronous code such as
setTimeout, promises andfetchcallbacks. Catch them yourself and store the error in state (see Error States). One trick: in an async handler, store the error in state and throw it during render so the boundary catches it. - Server-side rendering errors.
- Errors in the boundary itself. A boundary catches errors in its children, not in itself.
Where to put them
- Around the whole app: the last line of defence, with a friendly “something went wrong, reload” page.
- Around independent sections (a sidebar, a chart, a widget): a broken part shows its own fallback while the rest still works.
- Around routes: a page that crashes keeps the menu working. React Router’s
ErrorBoundaryroute property does this for you (Not Found Pages).
Several small boundaries beat one giant one, because the fallback appears where the failure is.
The fallback
Make the fallback useful: say what happened in plain words, offer Try again or a way back, and never show stack traces to users. Log the technical details privately.
react-error-boundary package
Writing the class each time is tedious, so most projects use the small react-error-boundary package. It provides an ErrorBoundary component with fallback, FallbackComponent and onReset props, and a useErrorBoundary hook for async errors. It is installed with npm install react-error-boundary in a real project, so it does not run in the playground. The example above shows what it does for you.
In development vs production
In development, React still shows its own error overlay (Vite’s overlay) on top of the page, even when a boundary catches the error. Close it to see your fallback. In production, only your fallback appears.
React 19 also lets you handle errors at the root: createRoot(el, { onCaughtError, onUncaughtError }) receive errors caught by boundaries and errors that were not caught, which is a convenient single place to report them.
Key points
- An error boundary is a class component with
getDerivedStateFromErrorandcomponentDidCatch. - It catches render-time errors in its children, not event handler or async errors.
- Place several boundaries around independent sections; log errors and show helpful fallbacks.