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)