Recipe
React error boundary patterns
Catch render-phase errors gracefully without unmounting the entire tree.
Class component boundary
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
console.error("Boundary caught:", error, info);
}
render() {
if (this.state.hasError) {
return this.props.fallback ?? <h2>Something went wrong.</h2>;
}
return this.props.children;
}
}Reset via key
function ResettableErrorBoundary({ children, fallback }) {
const [errorKey, setErrorKey] = React.useState(0);
return (
<ErrorBoundary
key={errorKey}
fallback={
<div>
{fallback}
<button onClick={() => setErrorKey(k => k + 1)}>
Retry
</button>
</div>
}
>
{children}
</ErrorBoundary>
);
}Event handler errors
Boundaries do not catch errors inside event handlers. Wrap with try/catch and set state.
function SafeButton() {
const [error, setError] = React.useState(null);
const handleClick = async () => {
try {
await riskyOperation();
} catch (e) {
setError(e.message);
}
};
if (error) return <p className="text-red-400">{error}</p>;
return <button onClick={handleClick}>Run</button>;
}Tip: Place boundaries around subtrees that depend on external data or third-party components. Keep fallbacks lightweight — avoid cascading failures.