如果一个组件渲染了10次,并且有一个错误,componentDidCatch()
将触发10次,并返回相同的错误。目前,我在catch上发出一个API请求来记录错误,但我只希望该错误被记录一次。
我的第一个想法是在状态中保存我自己的prevError
,并检查传递给componentDidCatch()
的error
是否相同。但这不会起作用,因为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
切换为类上的字段外,我还将其更改为数组,以便也跳过重复的错误-但两者之间可能存在不同的错误。
发布于 2018-08-28 07:19:55
在您发布的代码中,在setstate
回调函数第一次运行之前很久,componentDidCatch()
将快速连续地触发十几次。然而,prevError
不一定是state
的一部分,因为它对组件的外观没有影响。
只需将其实现为类变量,以便同步设置。
https://stackoverflow.com/questions/52042251
复制相似问题