A React error boundary only works when you trigger an error in the right place. If you throw in the wrong place, nothing happens and it feels broken.
Here is the practical way to trigger a React error boundary in both development and tests.
What an error boundary actually catches
A React error boundary catches errors from:
- rendering
- lifecycle methods
- constructors of child components
It does not catch errors from:
- event handlers
- async callbacks like
setTimeout - server-side rendering
So if you click a button and throw inside onClick, your boundary will not render fallback UI.
Quick way to trigger it in development
The easiest way is to throw during render behind a debug flag:
function Profile({ shouldCrash }: { shouldCrash: boolean }) {
if (shouldCrash) {
throw new Error("Intentional crash for testing boundary");
}
return <div>Profile loaded</div>;
}
Wrap it with a boundary:
import { ErrorBoundary } from "react-error-boundary";
<ErrorBoundary fallback={<p>Something went wrong.</p>}>
<Profile shouldCrash={true} />
</ErrorBoundary>;
If your fallback shows up, your React error boundary is wired correctly.
Reliable Jest test pattern
Use a component that throws on render and assert fallback output.
import { render, screen } from "@testing-library/react";
import { ErrorBoundary } from "react-error-boundary";
function CrashOnRender() {
throw new Error("boom");
}
test("renders fallback when child crashes", () => {
const spy = jest.spyOn(console, "error").mockImplementation(() => {});
render(
<ErrorBoundary fallback={<p data-testid="fallback">Fallback</p>}>
<CrashOnRender />
</ErrorBoundary>,
);
expect(screen.getByTestId("fallback")).toBeInTheDocument();
spy.mockRestore();
});
Why mock console.error? React logs the crash to console during tests and can flood output. You still test behavior, just without noisy logs.
Event handler caveat (important)
If your app fails inside onClick, a React error boundary will not catch it automatically.
Use useErrorBoundary from react-error-boundary and forward the error:
import { useErrorBoundary } from "react-error-boundary";
function SaveButton() {
const { showBoundary } = useErrorBoundary();
const handleClick = async () => {
try {
await saveData();
} catch (error) {
showBoundary(error);
}
};
return <button onClick={handleClick}>Save</button>;
}
Now the failure path from async or event-driven code can still reach your boundary fallback.
Conclusion
To trigger a React error boundary, throw during render for quick checks, and use a crash component in Jest for reliable tests. For event handler or async errors, send the error to the boundary explicitly with showBoundary.