How to Create a React Error Boundary Component in 2026
Why you need Error Boundaries in production
When a React component throws during rendering, the entire component tree unmounts — your users see a blank screen with no explanation. An Error Boundary is a wrapper component that catches rendering errors from its children and shows a fallback UI instead of crashing the whole app.
Before 2023, Error Boundaries required class components with componentDidCatch and getDerivedStateFromError. In 2026, the idiomatic approach is the react-error-boundary package, which provides a fully-featured boundary as a functional component.
The old way — class component (avoid in 2026)
❌ Outdated — class-based Error Boundary
// ❌ Works, but verbose and requires a class component.
// Not compatible with hooks. Avoid for new code.
import React from 'react';
class OldErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean }
> {
constructor(props: any) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error(error, info.componentStack);
}
render() {
if (this.state.hasError) return <h2>Something went wrong.</h2>;
return this.props.children;
}
}
The modern way — react-error-boundary
✅ Install the package
npm install react-error-boundary
# or
pnpm add react-error-boundary
Basic usage — drop-in wrapper
✅ Wrap any component tree prone to errors
// app/layout.tsx (Next.js App Router example)
"use client"; // Error Boundary must be a Client Component
import { ErrorBoundary } from 'react-error-boundary';
function FallbackUI({ error, resetErrorBoundary }: {
error: Error;
resetErrorBoundary: () => void;
}) {
return (
<div role="alert" style={{ padding: '2rem', textAlign: 'center' }}>
<h2>Something went wrong</h2>
<pre style={{ color: 'red', fontSize: '0.85rem' }}>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ErrorBoundary FallbackComponent={FallbackUI}>
{children}
</ErrorBoundary>
</body>
</html>
);
}
Auto-reset on route change (Next.js App Router)
After an error, the boundary stays in its error state even if the user navigates away. Use resetKeys to reset the boundary whenever the route changes.
✅ Auto-reset when pathname changes
"use client";
import { usePathname } from 'next/navigation';
import { ErrorBoundary } from 'react-error-boundary';
export function NavigationAwareErrorBoundary({
children
}: {
children: React.ReactNode
}) {
const pathname = usePathname();
return (
<ErrorBoundary
FallbackComponent={FallbackUI}
resetKeys={[pathname]} // boundary resets every time pathname changes
>
{children}
</ErrorBoundary>
);
}
Log errors to your monitoring service
Use the onError prop to send errors to Sentry, Datadog, or any observability platform.
✅ Connect to Sentry (or any logging service)
import * as Sentry from '@sentry/nextjs';
import { ErrorBoundary } from 'react-error-boundary';
function logBoundaryError(error: Error, info: { componentStack: string }) {
Sentry.withScope(scope => {
scope.setTag('source', 'error-boundary');
scope.setExtra('componentStack', info.componentStack);
Sentry.captureException(error);
});
}
export function MonitoredErrorBoundary({ children }: { children: React.ReactNode }) {
return (
<ErrorBoundary
FallbackComponent={FallbackUI}
onError={logBoundaryError}
>
{children}
</ErrorBoundary>
);
}
Trigger the boundary programmatically from async code
Error Boundaries only catch rendering errors. They do not catch errors inside event handlers or async useEffect calls. Use the useErrorBoundary hook to manually forward async errors to the nearest boundary.
✅ Forward async errors to the Error Boundary
import { useErrorBoundary } from 'react-error-boundary';
export function DataLoader() {
const { showBoundary } = useErrorBoundary();
useEffect(() => {
fetch('/api/data')
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
})
.then(setData)
.catch(showBoundary); // forwards error to nearest ErrorBoundary
}, [showBoundary]);
return <div>{data}</div>;
}
Frequently Asked Questions
Should I have one global Error Boundary or many nested ones?
Both. Use a global boundary at your app root as a last-resort catch-all. Then add local boundaries around isolated features (widgets, sidebars, data-heavy panels) so a crash in one section doesn't unmount the entire page. This gives users a degraded-but-functional experience instead of a blank screen.
Does Error Boundary work in React Server Components (Next.js App Router)?
Error Boundaries must be Client Components ("use client" at the top). Server Components use Next.js's built-in error.tsx file convention as their boundary equivalent. Place an error.tsx file in the same directory as a page.tsx to catch server-side render errors for that route segment.
What errors does Error Boundary NOT catch?
Error Boundaries do not catch: (1) errors in event handlers — use try/catch there, (2) errors in asynchronous code like setTimeout or fetch — use useErrorBoundary().showBoundary() as shown above, (3) errors during server-side rendering — use Next.js error.tsx, (4) errors thrown in the Error Boundary itself.