问题
React17 中错误边界(Error Boundaries)能正常捕获错误的场景有哪些?
选项
A. 绑定DOM的事件方法中的错误。
B. 异步代码中的错误。
C. 任意子组件树的渲染方法 render()
和所有生命周期方法中的错误。
D. 错误边界组件自身的错误。
答案
C
纠错
A. 绑定DOM的事件处理方法中的错误无法被捕获到。(因为在触发交互前,组件的生命周期和渲染都已经被执行。如果需要捕获事件的方法中的错误,需要使用 JS 的 try / catch
方法。)
B. 异步代码中的错误无法被捕获到。(包括 setTimeout、Promise 等,原因与A同理。)
D. 错误边界组件自身错误无法被捕获,而是会被上层的错误边界组件给获取。
解答
错误边界是一种 React 组件,这种组件可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。
错误边界组件
在 class 组件中定义了 static getDerivedStateFromError() 或 componentDidCatch() 这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
当抛出错误后,请使用 static getDerivedStateFromError()
渲染备用 UI ,使用 componentDidCatch()
打印错误信息。
备注:只有 class 组件才可以成为错误边界组件。
错误边界原理
当组织树种没有定义错误边界组件时,React16 之后的版本就会卸载掉报错的组件树。它和 try / catch
机制是完全一样的,假设有如下结构的4个组件:
- CompA
- CompB
- CompC1
- CompC2
- CompB
在没有错误边界的情况下,我们在 CompC1 的 render() 中抛出一个 Error 后,会导致上面的所有组件都被卸载掉。这时我再加入上面定义的错误边界组件来 catch 错误,调整如下:
- CompA
- CompB
- ErrorBoundary
- CompC1
- CompC2
- ErrorBoundary
- CompB
同样在 CompC1 组件抛出错误时,CompC1 和 CompC2 会被卸载掉,并且会启用 ErrorBoundary
组件中的 render 内容错误信息。
错误信息
假设我们在 render()
中抛出一个 new Error('I crashed!')
的错误时,可以在 componentDidCatch(error, errorInfo)
方法中会获得对应的错误详细信息,这里的 errorInfo
中的 componentStack
为 React 提供的组件堆栈信息。
in BuggyCounter (created by App)
in ErrorBoundary (created by App)
in div (created by App)
in App
而 err 对象为原生的 Error 对象,使用 error.toString()
可以打印出具体的报错描述: I crashed!
资料
zh-hans.reactjs.org/docs/error-…
来源
搜索《考试竞技》微信小程序