跳到主要内容

错误边界与调试

错误边界( Error Boundaries )React 中捕获子组件树错误并防止应用奔溃的核心机制。

信息

官方在提示中写道:

目前还没有办法将错误边界编写成函数式组件。但是无需自己编写错误边界类。可以使用 react error boundary 官方推荐包。

一、 错误边界基本原理

  • 定义 : Error Boundaries 是一个 React 组件,通过生命周期方法捕获子组件树中的 JavaScript 错误,记录错误日志并展示备用 UI
  • 作用范围 : 捕获子组件在渲染、生命周期方法、构造函数中的错误,但不捕获事件处理器、异常代码或服务端渲染错误
注意

错误边界不会捕获以下错误:

  • 事件处理程序(回调函数的错误应当使用 try...catch 进行捕获)
  • 服务端渲染(服务端渲染的逻辑也应当在 try...catch 中进行捕获)
  • 在错误边界本身(为不是其子集)中引发的错误
  • 异步代码(例如 setTimeoutrequestAnimationFrame 回调);一个例外useTransition Hook 返回的 startTransition() 函数的用法。在过度函数中抛出的错误会被错误边界捕获。

1. 实现原理

要实现错误边界,需要提供 static getDerivedStateFromError ,它允许更新状态以响应错误并向用户显示错误消息。

还可以实现 componentDidCatch 来添加一些额外的逻辑,例如将错误添加到分析服务。

二、 创建错误边界组件

class ErrorBoundary extends React.Component {
state = {
hasError: false,
error: null,
errorInfo: null,
};

constructor(props) {
super(props);
}

// 捕获错误并更新状态
static getDerivedStateFromError(error) {
return {
hasError: true,
error,
};
}
// 记录错误日志(可对接 Sentry 等监控工具)
componentDidCatch(error, errorInfo) {
console.error('未捕获错误', error, errorInfo);
logErrorToMyService(error, errorInfo); // 上报错误
}

// 重置错误状态
resetError = () => {
this.setState({
hasError: false,
error: null,
});
};

render() {
if (this.state.hasError) {
if (this.props.fallback) return this.props.fallback;

// 在触发错误时,在这里渲染自定义的后备 UI
return (
<div className="error-callback">
<h3>页面加载失败</h3>
<button onClick={this.resetError}>重置</button>
{/** 可添加错误详情按钮(开发环境展示) */}
{process.env.NODE_ENV === 'development' && (
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error?.toString()}
<br />
{this.state.errorInfo?.componentStack}
</details>
)}
</div>
);
}
// 正常渲染子组件
return this.props.children;
}
}

三、使用

使用上面包装的组件包装组件树的一部分:

<ErrorBoundary fallback={<p>一些小小的错误</p>}>
<Profile />
</ErrorBoundary>
信息

不需要将每一个组件单独包装到单独的错误边界中。当考虑 错误边界的布置 时,考虑在哪里显示错误消息才有意义。