字
字节笔记本
2026年2月22日
手把手教你实现 react-error-boundary
本文介绍一个手把手教你实现 react-error-boundary 的开源项目。该项目通过实战教程,详细讲解如何从零开始构建一个功能完善的 React 错误边界组件,帮助开发者更好地处理 React 应用中的异常错误。
项目简介
my-react-error-bounday 是一个由 haixiangyan 开发的开源教学项目,旨在通过造轮子的方式帮助开发者深入理解 React Error Boundary 的工作原理。截至目前,该项目在 GitHub 上已获得 65 stars,主要使用 TypeScript (86.6%) 编写。
项目通过生动有趣的故事形式,从实际开发中遇到的问题出发,逐步引导开发者实现一个功能完整的 Error Boundary 组件。
核心特性
- 完整的类型支持:使用 TypeScript 编写,提供完整的类型定义
- 多种 fallback 展示方式:支持 fallback 元素、FallbackComponent 组件、fallbackRender 函数三种方式
- 手动重置功能:提供 onReset 和 resetErrorBoundary 方法实现手动重置
- 自动重置机制:通过 resetKeys 监听数组变化自动重置错误状态
- 高阶组件支持:提供 withErrorBoundary 高阶函数简化组件包裹
- 自定义错误处理:提供 useErrorHandler Hook 让开发者自主抛出错误
技术栈
- React:核心 UI 框架
- TypeScript:类型安全的 JavaScript 超集
- React Hooks:使用 useState 等 Hooks 实现状态管理
核心概念
Error Boundary 是什么
Error Boundary 是 React 提供的一种错误处理机制,用于捕获子组件树中的 JavaScript 错误,记录这些错误,并显示备用 UI 而不是让组件树崩溃。
关键生命周期方法
- getDerivedStateFromError:当错误发生时更新 state,使下一次渲染显示降级 UI
- componentDidCatch:捕获错误信息,可用于错误日志上报
实现步骤
第一步:基础 ErrorBoundary
从 React 官网示例开始,创建一个基础的 ErrorBoundary 类组件:
typescript
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
logger.error(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}第二步:灵活的 Fallback 配置
扩展组件以支持多种 fallback 传入方式:
typescript
interface FallbackProps {
error: Error;
}
interface ErrorBoundaryProps {
fallback?: React.ReactElement;
FallbackComponent?: React.ComponentType<FallbackProps>;
fallbackRender?: (props: FallbackProps) => React.ReactElement;
onError?: (error: Error, info: string) => void;
}
// 在 render 中根据优先级选择 fallback 展示方式
if (error !== null) {
if (React.isValidElement(fallback)) {
return fallback;
}
if (typeof fallbackRender === 'function') {
return fallbackRender({ error });
}
if (FallbackComponent) {
return <FallbackComponent error={error} />;
}
}第三步:添加重置功能
实现手动重置和自动重置机制:
typescript
interface ErrorBoundaryProps {
// ... 其他 props
onReset?: () => void;
resetKeys?: Array<string | number>;
onResetKeysChange?: (prevKeys: Array<string | number>,
newKeys: Array<string | number>) => void;
}
resetErrorBoundary = () => {
if (this.props.onReset) {
this.props.onReset();
}
this.setState({ error: null });
}第四步:高阶组件封装
提供 withErrorBoundary 简化组件包裹:
typescript
function withErrorBoundary<P>(
Component: React.ComponentType<P>,
errorBoundaryProps: ErrorBoundaryProps
): React.ComponentType<P> {
const Wrapped: React.ComponentType<P> = props => {
return (
<ErrorBoundary {...errorBoundaryProps}>
<Component {...props}/>
</ErrorBoundary>
)
}
const name = Component.displayName || Component.name || 'Unknown';
Wrapped.displayName = `withErrorBoundary(${name})`;
return Wrapped;
}第五步:自定义错误抛出
提供 useErrorHandler Hook 处理非自动捕获的错误:
typescript
function useErrorHandler<P = Error>(
givenError?: P | null | undefined,
): React.Dispatch<React.SetStateAction<P | null>> {
const [error, setError] = React.useState<P | null>(null);
if (givenError) throw givenError;
if (error) throw error;
return setError;
}使用示例
基础用法
tsx
<ErrorBoundary fallback={<div>出错了</div>}>
<UserList />
</ErrorBoundary>使用 FallbackComponent
tsx
const ErrorFallback = ({ error }: { error: Error }) => (
<div>
<h2>出错了</h2>
<p>{error.message}</p>
</div>
);
<ErrorBoundary FallbackComponent={ErrorFallback}>
<UserList />
</ErrorBoundary>使用高阶组件
tsx
const UserWithErrorBoundary = withErrorBoundary(User, {
onError: (error) => console.error('出错:', error),
onReset: () => console.log('已重置')
});
// 在父组件中直接使用
const App = () => <UserWithErrorBoundary />;配合自定义错误处理
tsx
function Greeting() {
const [name, setName] = React.useState('');
const { greeting, error } = useGreeting(name);
// 将错误抛给 ErrorBoundary 处理
useErrorHandler(error);
return greeting ? <div>{greeting}</div> : <Form />;
}
export default withErrorBoundary(Greeting);最佳实践
- 合理放置 ErrorBoundary:在关键业务组件外层包裹 ErrorBoundary,避免整个应用崩溃
- 提供友好的错误提示:fallback UI 应该清晰告知用户发生了什么,并提供操作建议
- 错误上报:在 onError 回调中将错误信息上报到监控系统
- 重置策略:根据业务场景选择手动重置或自动重置
项目链接
- GitHub 仓库:https://github.com/Haixiang6123/my-react-error-bounday
- 在线演示:https://yanhaixiang.com/my-react-error-bounday/
- 参考轮子:https://www.npmjs.com/package/react-error-boundary
总结
my-react-error-bounday 项目通过一个生动有趣的故事,完整地演示了如何从零实现一个生产级的 React Error Boundary 组件。项目不仅实现了基础功能,还提供了多种灵活的使用方式,是学习 React 错误处理机制的绝佳教程。
分享: