I am trying to create an error boundary but it not working. The componentDidCatch not firing.
I expected that the fallback UI will render but actually the original UI is still there and nothing is happening.
const SimpleBtn = lazy(() => import("./componentJsx/SimpleBtn.jsx"));
const SimpleBtn2 = lazy(() => import("./componentJsx/SimpleBtn2.jsx"));
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: "", errorInfo: "" };
}
static getDerivedStateFromError(error) {
return error;
}
componentDidCatch(error, errorInfo) {
this.setState({ error, errorInfo });
console.log(error, errorInfo);
}
render() {
return this.state.errorInfo ? (
<>
<h3>Something is wrong!</h3>
<details>{this.state.error}</details>
</>
) : (
this.props.children
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = { toggle: false, hasError: false };
}
toggleBtn = () => {
// use transition
startTransition(() => {
this.setState((state) => ({
toggle: !state.toggle,
}));
});
};
render() {
const { toggle } = this.state;
return (
<ErrorBoundary>
<Suspense fallback={<div>...Loading</div>}>
<h1> Sample file </h1>
{toggle && <SimpleBtn toggleBtn={this.toggleBtn} />}
<SimpleBtn2 toggleBtn={this.toggleBtn} />
<button
onClick={() => {
throw new Error("i am error!");
}}
>
Throw Error
</button>
</Suspense>
</ErrorBoundary>
);
}
}
CodePudding user response:
This is because error boundaries only work for errors thrown during render. If you throw an error in a component render function instead it will work.
If you want to capture errors in event handlers you'll need to register an error handler on the window or do local error handling.
If youre just trying to test your error boundary throw in a component render instead and conditionally load that component if you like.
See https://reactjs.org/docs/error-boundaries.html#how-about-event-handlers