有两个功能组件。在点击事件处理程序 doStuff
中抛出了一个未知和意外的错误。 意外意味着我不能像往常一样使用 try...catch...
语句。
我已阅读 Error Boundaries,但它似乎只适用于基于类的组件。
我怎样才能发现错误并从这种情况中恢复过来?
附加上下文:我无法修改 Child
组件的代码。
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>;
}
答案 0 :(得分:1)
我不确定您对 I can't use the try...catch... statement as usual
的意思。我会使用一个可以捕获错误的委托函数。
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>
答案 1 :(得分:1)
我认为你可以像这样创建错误边界钩子
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);
}
然后,你可以使用
const Parent = withCatchError(() => {
const { error } = useCatchError();
if (error) return <div>Some error</div>
return ...
})
错误边界无法捕获每个错误。它只能捕获渲染错误。如果你想捕获所有的错误,你可以这样做
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;
}
然后你就可以使用
function Parent() {
const error = useCatchGlobalError();
...
}