Reputation: 102247
There are two functional components. An unknown and unexpected error is thrown out in the click event handler doStuff
. unexpected means I can't use the try...catch...
statement as usual.
I have read Error Boundaries, but it seems to only work for the class-based components.
How can I catch the error and recover from this situation?
Additional context: I can't modify the code of the Child
component.
import React from 'react';
function Child() {
function doStuff() {
throw new Error('An unknown and unexpected error from somewhere');
}
return <p onClick={doStuff}>my-button</p>;
}
function Parent() {
// How to catch the click event handler error in parent
return <Child></Child>;
}
Upvotes: 3
Views: 1641
Reputation: 11171
I think you can create the error boundary hook like this
const CatchErrorContext = React.createContext({});
function withCatchError(Component) {
return class extends React.Component {
componentDidCatch(error, errorInfo) {
this.setState({ error, errorInfo });
}
render() {
return (
<CatchErrorContext.Provider value={{ ...this.state }}>
<Component {...this.props} />
</CatchErrorContext.Provider>
);
}
};
}
function useCatchError() {
return useContext(CatchErrorContext);
}
Then, you can use
const Parent = withCatchError(() => {
const { error } = useCatchError();
if (error) return <div>Some error</div>
return ...
})
The error boundary cannot catch every error. It can only catch the rendering error. If you want to catch all the error, you can do something like this
function useCatchGlobalError() {
const [error, setError] = useState(null);
useEffect(() => {
const errorHandler = (e) => {
setError(e);
return true;
};
window.addEventListener("error", errorHandler);
return () => window.removeEventListener("error", errorHandler);
}, []);
return error;
}
Then you can use
function Parent() {
const error = useCatchGlobalError();
...
}
Upvotes: 3
Reputation: 51353
I'm not sure what you mean with a I can't use the try...catch... statement as usual
. I would use a delegate function that can catch the error.
function Child() {
function doStuff() {
throw new Error('An unknown and unexpected error from somewhere');
}
function tryDoStuff(){
try {
doStuff()
} catch (e) {
console.log("Caught: " + e);
}
}
return <button onClick={tryDoStuff} className="btn btn-primary">my-button</button>;
}
function Parent() {
// How to catch the click event handler error in parent
return <Child></Child>;
}
ReactDOM.render(<Parent/>, document.getElementById("root"));
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 1