Error Boundaries — the catch net

[check: …]
📖 guide (.md) ← react deep dive
📖 Pair this live React playground with the companion guide (.md) — this page is the rendered ground truth. ↗ Error boundaries catch render errors — effects need their own try/catch (errors in useEffect, setTimeout, and event handlers are NOT caught).

the catch net: why error boundaries exist

When a component throws during render, React unmounts the entire component tree — the whole screen goes white. An error boundary is a class component that acts as a try/catch for its subtree: it catches the error and renders a fallback UI instead of crashing the app. Define static getDerivedStateFromError(error) to update state (pure — return the new state), and componentDidCatch(error, info) for side effects (logging, analytics).

error sourcecaught by boundary?where to handle instead
render phase (JSX, function body) YES —
lifecycle methods (constructor, render, shouldComponentUpdate…) YES —
child component constructors + render YES —
event handlers (onClick, onSubmit…) NO try / catch inside the handler
async code (fetch, await, promises) NO .catch() / try / catch
setTimeout, setInterval, requestAnimationFrame NO try / catch inside the callback
errors thrown IN the boundary itself NO a parent boundary, or it crashes

1 · the boundary you write (edit me)

2 · Babel compiles JSX → element tree

<ErrorBoundary> becomes React.createElement(ErrorBoundary, { '{ key: resetKey }' }). When BombComponent throws, React unwinds to the nearest boundary and re-renders it with hasError: true.

// (hit "compile & render" to see Babel's output)

3 · live React (catch → fallback → recover)

Click "Trigger Error" to make BombComponent throw during render. The boundary catches it and shows the fallback. Click "Reset" to remount the boundary (new key) and recover. The gold-check does this automatically: assert safe → crash → assert fallback → reset → assert safe.

state: — · gold: safe → trigger → fallback → reset → safe

lifecycle → pattern

stepmethodrole
1 · catch static getDerivedStateFromError(error) PURE — return {'{ hasError: true }'} to switch to fallback
2 · log componentDidCatch(error, info) SIDE EFFECT — send to Sentry/analytics; info.componentStack has the trace
3 · render if (this.state.hasError) return <Fallback/> show fallback UI instead of the crashed children
4 · recover change key on the boundary remounts the boundary — hasError resets to false
React 19 createRoot(el, { '{ onCaughtError }' }) root-level callback for caught errors (replaces default console.error)