Explain how React Error Boundaries prevent a whole app from crashing due to rendering errors by showing a fallback UI, what they catch (render/lifecycle/constructor errors in descendants), and what they do NOT catch (event handlers, async code, SSR, and errors inside the boundary itself).
What problem do Error Boundaries solve? What don’t they catch?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Short answer
Error Boundaries solve the problem of UI tree crashes. If a component throws during rendering, React can replace that broken subtree with a fallback UI instead of unmounting the entire app (or leaving a blank screen).
What they are (mental model)
An Error Boundary is like a seatbelt for a part of your component tree.
Without it: one render error can crash the whole render path.
With it: React catches the error and renders a fallback for that subtree.
What Error Boundaries catch | Where the error happens | Why it matters |
|---|---|---|
Errors during rendering | While React is computing the UI output | Prevents blank screens / app crashes |
Errors in lifecycle methods (class components) | componentDidMount / componentDidUpdate, etc. | Lets you recover with fallback UI |
Errors in constructors (class components) | During component creation | Stops faulty subtree from taking down the app |
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
// log to monitoring (Sentry, etc.)
console.error(error, info);
}
render() {
if (this.state.hasError) {
return <div>Something went wrong.</div>;
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary>
<BuggyWidget />
</ErrorBoundary>
);
}
Key limitation
Error Boundaries only catch errors that happen while React is rendering/committing the UI tree for descendants.
They are not a general-purpose try/catch for everything in your app.
What they do NOT catch | Example | How to handle instead |
|---|---|---|
Event handler errors | onClick / onSubmit throws | Use try/catch in the handler + report/log |
Async errors | setTimeout / promise / async/await throws | Catch with .catch / try/catch and set error state |
Errors in the Error Boundary itself | Fallback UI throws | Wrap higher or fix boundary; keep fallback simple |
Errors outside React tree | Global scripts, non-React code | window.onerror / monitoring integration |
SSR rendering errors (server-side) | Server render throws before client loads | Handle on server/framework level + return error page |
function Button() {
const onClick = () => {
// ❌ Error Boundaries do NOT catch this
throw new Error('Boom in event handler');
};
return <button onClick={onClick}>Click me</button>;
}
function SaferButton() {
const onClick = () => {
try {
throw new Error('Boom');
} catch (e) {
// ✅ handle + report
console.error(e);
}
};
return <button onClick={onClick}>Click me</button>;
}
Where to place Error Boundaries (practical)
Don’t wrap the entire app with one giant boundary only. Use a few strategically placed boundaries so failure is isolated:
• Page-level boundary (keeps navbar/layout alive)
• Widget/card boundary (dashboard tiles don’t nuke the whole page)
• Route boundary (one route fails, rest of app still usable)
Rule of thumb
Use Error Boundaries to protect the UI tree from render-time crashes. Use normal error handling for user interactions and async work.
Interview framing
Say it like this:
"Error Boundaries catch errors during rendering and lifecycle/constructor of descendants, letting React show a fallback UI instead of crashing the whole tree. They do not catch errors in event handlers, async callbacks, SSR, or errors inside the boundary itself — those need explicit try/catch or promise handling."
Error Boundaries prevent render-time exceptions in a subtree from crashing the entire UI by rendering a fallback and optionally reporting the error. They catch render/commit-time errors in descendants but not event handler errors, async errors, SSR errors, or errors in the boundary itself.