Catch React errors with error boundaries, handle lifecycle errors, and display fallback UI gracefully.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}getDerivedStateFromError to update state when an error occurs.componentDidCatch to log errors for debugging.class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
console.error("Error caught:", error);
console.error("Error info:", errorInfo.componentStack);
// Send to error tracking service
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong</h1>;
}
return this.props.children;
}
}componentDidCatch is called after an error has been thrown.componentDidCatch itself.// This error is caught
function Child() {
throw new Error("Oops");
}
<ErrorBoundary>
<Child /> {/* Error is caught here */}
</ErrorBoundary>// This error is NOT caught
<button onClick={() => {
throw new Error("Oops");
}}>
Click me
</button>
// Use try-catch for these instead
<button onClick={() => {
try {
riskyOperation();
} catch (error) {
// Handle error
}
}}>
Safe click
</button><ErrorBoundary>
<Header />
<ErrorBoundary>
<MainContent />
</ErrorBoundary>
<Sidebar />
</ErrorBoundary>class ErrorBoundary extends React.Component {
render() {
if (this.state.hasError) {
return (
<div>
<h1>Oops, something went wrong</h1>
<p>Please try refreshing the page</p>
<button onClick={() => window.location.reload()}>
Reload Page
</button>
</div>
);
}
return this.props.children;
}
}<PageErrorBoundary>
<PageContent />
</PageErrorBoundary>Define a class component that implements getDerivedStateFromError to update state when an error is caught, then return fallback UI in render when that state is set. You can also implement componentDidCatch to receive the error and info objects for logging.
Error boundaries only intercept errors thrown during the React render cycle — event handlers run outside that cycle, so you need a try-catch block inside the handler itself.
Yes, and it's the recommended approach — nest them so a broken widget or feature only unmounts its own subtree while the rest of the page stays functional. Placing one at the root acts as a last-resort safety net, not a replacement for granular boundaries.
Implement componentDidCatch(error, info) in your class component and call your logging service there — info.componentStack gives you the full component trace, which is invaluable for debugging production issues.
No — as of React 18, error boundaries must be class components because the required lifecycle methods (getDerivedStateFromError, componentDidCatch) have no hook equivalents. Libraries like react-error-boundary wrap this pattern into a reusable component so you can use it declaratively without writing the class yourself.