React 错误边界详解
React 错误边界
React错误边界的本质上是防止子组件错误(渲染过程中)向上冒泡导致整个应用崩溃,错误边界可以解决导致整个应用崩溃问题。
在 React 错误边界中,fallback 确实实现了典型的降级策略:
- 理想情况:正常渲染业务组件
- 异常情况:当组件崩溃时,降级显示预设的备用 UI(组件降级机制)
降级的具体表现
| 降级前 (正常状态) | 降级后 (错误状态) |
|---|---|
| 完整的业务组件功能 | 简化的备用界面 |
| 复杂交互逻辑 | 可能只保留基本信息和操作 |
| 动态数据展示 | 静态错误提示 |
| 完整用户体验 | 最小可用性保障 |
// 正常情况:显示复杂的数据可视化图表
<DataVisualization complexData={data} />
// 降级情况:图表组件崩溃后显示简单的表格数据
<ErrorBoundary
fallback={<DataTable basicData={data} />} // 降级为简单表格
>
<DataVisualization complexData={data} />
</ErrorBoundary>
降级的实现
import React from 'react';
export default class ErrorBoundary extends React.Component {
constructor() {
super();
this.state = { hasError: false, errInfo: null };
}
reset() {
this.setState({
hasError: false
});
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能够显示降级后的 UI
return { hasError: true, errInfo: error.toString() };
}
componentDidCatch(error, errorInfo) {
// 可以将错误日志上报给服务器
// logErrorToMyService(error, errorInfo);
}
render() {
const { hasError, errInfo } = this.state;
const { fallback, children } = this.props;
if(hasError) {
// 如果提供了函数式fallback,传入错误和重置方法
if(typeof fallback == 'function') {
return fallback({ hasError, errInfo, resetErrorBoundary: this.reset });
}
return fallback || <div>{`组件出错了----->${errInfo}`}</div>
}
return children;
}
}
降级策略的层次
1.完全降级:显示完全不同的备用组件
fallback={<ErrorScreen />}
2.部分降级:显示简化版本的组件
fallback={<SimplifiedComponent />}
3.静默降级:隐藏出错部分不影响其他内容
fallback={null}
4.智能降级:根据错误类型显示不同fallback
fallback={(error) =>
error.type === 'API_ERROR'
? <NetworkError />
: <GenericError />
}
降级的时机(捕获范围)
会触发降级的情况(错误边界会捕获)
1.组件渲染期间的错误
function BuggyComponent() {
// 渲染时抛出错误会被捕获
throw new Error('Render error');
return <div>正常内容</div>;
}
2. 生命周期方法中的错误
class BuggyComponent extends React.Component {
componentDidMount() {
// 生命周期中的错误会被捕获
throw new Error('Lifecycle error');
}
render() { return <div>内容</div>; }
}
3.构造函数中的错误
class BuggyComponent extends React.Component {
constructor(props) {
super(props);
// 构造函数错误会被捕获
throw new Error('Constructor error');
}
render() { return <div>内容</div>; }
}
4.子组件树中任何上述错误
<ErrorBoundary>
<Parent> {/* 即使错误发生在深层子组件也会被捕获 */}
<Child>
<GrandChildWithError />
</Child>
</Parent>
</ErrorBoundary>
不会触发降级的情况(错误边界不会捕获)
1.事件处理函数中的错误
function Component() {
const handleClick = () => {
// 事件处理器错误不会被捕获
throw new Error('Event handler error');
};
return <button onClick={handleClick}>点击</button>;
}
2.异步代码中的错误
useEffect(() => {
// 异步错误不会被捕获
setTimeout(() => { throw new Error('Async error') }, 1000);
}, []);
3.错误边界组件自身抛出的错误
class BuggyErrorBoundary extends ErrorBoundary {
render() {
// 错误边界自身的错误不会被捕获
throw new Error('Error boundary itself error');
return super.render();
}
}
4.React 事件系统的错误
5.服务端渲染的错误
降级应用场景
1. 数据加载组件
场景:API 数据加载组件
<ErrorBoundary
fallback={({ resetErrorBoundary }) => (
<div>
<p>数据加载失败</p>
<button onClick={resetErrorBoundary}>重试</button>
</div>
)}
>
<AsyncDataLoader userId={123} /> {/* 可能因API异常崩溃 */}
</ErrorBoundary>
作用:网络请求失败时提供重试机制,而非白屏
2. 路由级页面保护
场景:防止整个路由页面崩溃
function App() {
return (
<Router>
<ErrorBoundary fallback={<PageErrorScreen />}>
<Switch>
<Route path="/dashboard" component={Dashboard} /> {/* 复杂仪表板 */}
<Route path="/editor" component={RichTextEditor} /> {/* 易崩溃的编辑器 */}
</Switch>
</ErrorBoundary>
</Router>
);
}
作用:单个页面崩溃时显示全屏错误页,仍可通过导航切换其他页面
3. 第三方组件容错
<ErrorBoundary
fallback={<DataTable data={rawData} />} // 降级为表格展示
>
<ThirdPartyChart data={processedData} /> {/* 可能因数据格式异常崩溃 */}
</ErrorBoundary>
作用:当图表库因数据格式异常崩溃时,自动切换为原始数据表格展示

浙公网安备 33010602011771号