React 错误边界与 Suspense:优雅处理渲染异常与异步加载
test12026-09-122 次阅读
为什么需要错误边界
React 渲染期间抛出的错误如果不加处理,会从最近的边界一直冒泡到根组件,导致整棵树卸载、页面白屏。错误边界(Error Boundary)是 React 唯一能捕获渲染期异常的机制,它本质是一个实现了 getDerivedStateFromError 或 componentDidCatch 生命周期方法的类组件。
实现一个最小错误边界
注意:错误边界只能用类组件写,因为它依赖生命周期方法。函数组件没有等价 API,所以这是 React 里少数仍需类组件的场景。
import { Component, ReactNode } from 'react';
interface Props {
fallback: ReactNode;
children: ReactNode;
}
interface State {
hasError: boolean;
}
export class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false };
static getDerivedStateFromError(): State {
return { hasError: true };
}
componentDidCatch(error: Error) {
console.error('render error:', error);
}
render() {
if (this.state.hasError) return this.props.fallback;
return this.props.children;
}
}
配合 Suspense 处理异步加载
Suspense 负责在资源未就绪时展示 fallback,错误边界负责在资源或渲染失败时兜底。两者职责不同,要嵌套使用:外层 ErrorBoundary 捕获失败,内层 Suspense 展示加载中。
import { Suspense, lazy } from 'react';
const Chart = lazy(() => import('./Chart'));
function Page() {
return (
<ErrorBoundary fallback={<p>图表加载失败</p>}>
<Suspense fallback={<p>加载中…</p>}>
<Chart />
</Suspense>
</ErrorBoundary>
);
}
让数据获取也能被 Suspense 捕获
React 18 的 Suspense 本身不获取数据,需要你提供一个在 pending 时 throw promise、在 rejected 时 throw error 的资源对象。下面是最简化的 suspense 资源封装:
function wrapPromise<T>(promise: Promise<T>) {
let status = 'pending';
let result: T;
const suspender = promise.then(
(r) => { status = 'success'; result = r; },
(e) => { status = 'error'; result = e; }
);
return {
read(): T {
if (status === 'pending') throw suspender;
if (status === 'error') throw result;
return result;
}
};
}
三个容易踩的坑
- 错误边界不能捕获事件处理函数里的异常,按钮 onClick 里的错误要用 try/catch 自己处理。
- 一个错误边界只兜住它子树里的渲染错误,建议按功能模块粒度放置,而不是只在根上放一个。
- 错误边界自身抛错会冒泡到更外层边界,生产环境务必配合监控上报,否则白屏无日志。
T
test1
文章作者
为什么需要错误边界 React 渲染期间抛出的错误如果不加处理,会从最近的边界一直冒泡到根组件,导致整棵树卸载、页面白...
- 分类
- 技术
- 发布时间
- 2026-09-12
- 字数
- 约 1901 字
- 阅读
- 2 次
