如果某个组件渲染了10次,并且有错误,则componentDidCatch()
将因相同的错误触发10次。目前,我正在捕获一个API请求以记录该错误,但是我只希望将该错误记录一次。
我的第一个操作是将自己的prevError
保存为状态,并检查传递给error
的componentDidCatch()
是否相同。但这是行不通的,因为setState
请求不是立即发出的。其他一些生命周期事件通过了最新状态,但事实并非如此。我知道setState()
接受具有最新状态的回调,但是到那时错误将始终等于prevError
。这就是我的意思:
componentDidCatch(error, info) {
this.setState({ error: true });
const isNewError = (error.toString() !== this.state.prevError.toString());
// always true since setState is async
if (isNewError) {
logErrorToMyService(error, info); // should only run once
this.setState({ prevError: error });
}
}
我也不认为我可以使用
componentDidUpdate()
,因为那不知道我的错误。我想念什么吗?我是在错误地处理此问题,是否需要对其进行重新处理(也许将支票移到
logErrorToMyService
中)?我的意思的完整React示例:
const logErrorToMyService = () => console.warn('I should only be run once');
class ErrorBoundary extends React.Component {
state = {
error: false,
prevError: new Error(),
}
componentDidCatch(error, info) {
this.setState({ error: true });
// none of the below code will work correctly
const isNewError = (error.toString() !== this.state.prevError.toString());
// always true since setState is async
if (isNewError) {
logErrorToMyService(error, info); // should only run once
this.setState({ prevError: error });
}
}
render() {
if (this.state.error) {
return <div>Something went (purposefully) wrong.</div>;
}
return this.props.children;
}
}
// below is 10 purposefully buggy component instances
const BuggyComponent = () => (
<div>{purposefully.throwing.error}</div>
)
const App = () => (
<ErrorBoundary>
{[...Array(10)].map((_, i) => <BuggyComponent key={i} />)}
</ErrorBoundary>
)
ReactDOM.render(
<App />,
document.getElementById('root')
);
<div id='root'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.3.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.1/umd/react-dom.development.js"></script>
更新:除了将
prevError
切换到类中的字段之外,我还将其更改为数组,从而也可以跳过重复错误-但两者之间可能有不同的错误。 最佳答案
在您发布的代码中,componentDidCatch()
将迅速连续触发大约十二次,这要早于setstate
回调首次运行之前。但是prevError
不必是state
的一部分,因为它与组件的外观无关。
只需将其实现为类变量,即可同步设置。
关于javascript - 如何避免componentDidCatch()多次触发?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52042251/