The Problem: One Error Crashes Everything
By default, a JavaScript error thrown anywhere during rendering unmounts the entire React component tree, showing a blank page — even if the error came from one small, unrelated widget.
What is an Error Boundary?
An error boundary is a component that catches JavaScript errors thrown by its children during rendering, logs them, and displays a fallback UI instead of crashing the whole app.
A Basic Error Boundary
import { Component } from "react";
class ErrorBoundary extends Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error("Caught by ErrorBoundary:", error, info);
}
render() {
if (this.state.hasError) {
return <h2>Something went wrong.</h2>;
}
return this.props.children;
}
}Wrapping Part of the UI
function App() {
return (
<div>
<Header />
<ErrorBoundary>
<Dashboard /> {/* if this throws, only this part is replaced */}
</ErrorBoundary>
<Footer />
</div>
);
}Error Boundaries Must Be Class Components
As of current React versions, error boundaries can only be implemented as class components — there is no hook equivalent yet, since getDerivedStateFromError and componentDidCatch have no direct functional-component counterpart.
What Error Boundaries Don’t Catch
Error boundaries only catch errors during rendering, in lifecycle methods, and in constructors of the tree below them. They do not catch errors inside event handlers, asynchronous code (like a setTimeout callback), or server-side rendering.
Handling an Event Handler Error Separately
function SaveButton() {
function handleClick() {
try {
saveData();
} catch (error) {
console.error("Failed to save:", error);
// handle it directly — an ErrorBoundary won't catch this
}
}
return <button onClick={handleClick}>Save</button>;
}Third-Party Libraries Simplify This
Because writing a class-based error boundary from scratch is repetitive boilerplate, many teams use a small, well-tested library like react-error-boundary, which provides a ready-made <ErrorBoundary> component with a fallback prop.
Best Practice
Place error boundaries around independent sections of a page (a widget, a chart, a third-party embed) rather than one single boundary around the entire app — this way, one broken feature doesn’t take down the rest of the page.