1. 错误边界是什么?
- React中,组件的JavaScript错误不应该破坏整个应用程序。为了解决这个问题,React16引入了“错误边界”的新概念。
- 错误边界也是 React 组件,它可以在子组件树的任何位置捕获 JavaScript 错误,记录这些错误,并显示一个备用UI(UI降级) ,而不是使整个组件树崩溃。
2. 错误边界有什么限制?
- 无法捕获的错误
- 事件中的错误,比如click事件中发生的错误
- 异步代码 (例如
setTimeout或requestAnimationFrame回调函数) - 服务端渲染
- 错误边界自身抛出来的错误 (而不是其子组件)
- 使用时只能是class组件
- 错误边界组件目前只支持class组件的方式创建。
3. 如何实现一个错误边界?
-
创建一个类组件,组件中包含
getDerivedStateFromError和componentDidCatch两个声明周期函数。 -
getDerivedStateFromError
- 该函数为静态函数
static getDerivedStateFromError - 函数执行时间点:页面更新前,子组件渲染出现错误之后。
- 只有子组件发生错误时,该函数才会被执行
- 该函数返回一个对象,该对象的返回值会覆盖掉当前组件的state
- 参数 错误对象Error
- 该函数为静态函数
-
componentDidCatch
- 捕捉错误生命周期函数
- 参数:1. error:错误对象 {message:string, stack:string} 2.errorInfo 错误信息 {componentStack :string}
- 基本用来处理错误产生之后的上报和错误处理逻辑。
- 触发时间点:子组件报错后及组件更新之后。
-
代码demo
- ErrorBoundary组件
import React from "react";
import { Button } from "antd"
class ErrorBoundary extends React.Component<{ children: React.ReactNode }> {
state = {
error: null,// 是否存在错误
errMsg: ""
}
/**
* 捕捉错误,并且将错误添加到state中
* 若state存在该属性则覆盖,没有则添加
*
* @param err
* @returns
*/
static getDerivedStateFromError(err: Error) {
// 给state 中的error属性赋值
return { error:err }
}
/**
* 捕捉错误生命周期函数
* @param error 错误对象 {message:string, stack:string}
* @param errorInfo 错误信息 {componentStack :string}
*/
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
console.log("componentDidCatch error ", error, errorInfo)
// 上报错误或其他处理逻辑
this.setState({
errMsg: error
})
}
render() {
if (this.state.error) {
// return <div>{this.state.errMsg}</div>
return <div>
<div>
The Error Message:{this.state.errMsg?.message}
</div>
<section>
someThing was Wrong !
</section>
<Button onClick={() => window.location?.reload()}>点击刷新</Button>
</div>
}
return this.props.children;
}
}
export default ErrorBoundary;
- 使用
- 错误边界的使用粒度按实际业务控制,比如只对某些容易出现错误的组件做包裹即可,不影响其他组件的展示。
- 效果
- Header子组件故意触发错误 使用props.a.a(undefined.a)
子组件错误页面错误捕捉并且显示。
- 错误边界的使用粒度按实际业务控制,比如只对某些容易出现错误的组件做包裹即可,不影响其他组件的展示。