Simple reusable React error boundary component
react-error-boundary is a production-ready library that simplifies error handling in React applications by providing a declarative ErrorBoundary component. While React introduced error boundaries in version 16, implementing them requires writing class components with specific lifecycle methods. This package abstracts that complexity into a reusable component with modern hooks support.
The library solves a critical problem: unhandled JavaScript errors during rendering can crash entire React applications, leaving users with blank screens. By wrapping component trees in ErrorBoundary, developers catch these errors, log them for monitoring, and display user-friendly fallback UIs. With over 8.8 million weekly downloads, it's become the de facto standard for error handling in React ecosystems.
What sets this package apart is its developer experience. Beyond basic error catching, it provides reset mechanisms to retry failed renders, a useErrorBoundary hook for handling async errors (which traditional boundaries miss), and flexible fallback rendering options. It integrates seamlessly with frameworks like Next.js, though it requires client-side rendering. The API is intentionally minimal—error boundaries, fallback components, and reset callbacks—making it approachable for teams migrating from manual class-based implementations.
The library targets production applications where user experience and stability matter. It's particularly valuable in large codebases where a bug in one feature shouldn't take down unrelated parts of the UI, and in applications with complex async workflows where errors need manual boundary propagation.
import { ErrorBoundary, useErrorBoundary } from 'react-error-boundary';
import { useState } from 'react';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert" style={{ padding: '20px', border: '2px solid red' }}>
<h2>Something went wrong</h2>
<pre style={{ color: 'red', fontSize: '14px' }}>{error.message}</pre>
<button onClick={resetErrorBoundary}>Retry</button>
</div>
);
}
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const { showBoundary } = useErrorBoundary();
const fetchUser = async () => {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to load user');
setUser(await response.json());
} catch (error) {
showBoundary(error);
}
};
if (Math.random() > 0.7) {
throw new Error('Render error: Invalid user state');
}
return <div>{user ? user.name : <button onClick={fetchUser}>Load User</button>}</div>;
}
function App() {
const [userId, setUserId] = useState(1);
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => setUserId(prev => prev + 1)}
resetKeys={[userId]}
>
<UserProfile userId={userId} />
</ErrorBoundary>
);
}Route-level isolation in single-page applications: Wrap each route or page component in an ErrorBoundary so errors in one section don't crash the entire app. Users can navigate away from broken pages while developers receive isolated error reports.
Third-party component wrappers: Encapsulate external libraries or widgets (analytics, chat, ads) in boundaries to prevent their failures from affecting core functionality. If an ad provider's script throws, show a placeholder instead of breaking checkout.
Async data fetching with manual error handling: Use the useErrorBoundary hook inside components that fetch data with native fetch or axios. Catch promise rejections and call showBoundary(error) to propagate them to the nearest boundary, providing consistent error UI across sync and async failures.
Form submissions with retry logic: Wrap forms in boundaries with resetKeys tied to submission state. When network requests fail, users see the error and a retry button that calls resetErrorBoundary, which can trigger onReset to clear form state or refresh tokens before re-attempting.
Dashboard widgets with independent failure domains: In analytics dashboards or admin panels with multiple independent charts/tables, wrap each widget separately. One failing data source won't break others, and each gets its own error state and reload mechanism.
npm install react-error-boundarypnpm add react-error-boundarybun add react-error-boundary