问题
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
-
-
在没有错误边界的情况下,我们在 CompC1 的 render() 中抛出一个 Error 后,会导致上面的所有组件都被卸载掉。这时我再加入上面定义的错误边界组件来 catch 错误,调整如下:
-
CompA
-
CompB
-
ErrorBoundary
-
CompC1
-
CompC2
-
-
-
同样在 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!
资料
来源
搜索《考试竞技》微信小程序