说说你在 React 项目中是如何捕获错误的?
一、是什么
在 React 应用中,任何未被捕获的 JavaScript 错误都可能导致整个组件树崩溃,使用户看到白屏。React 16 引入了 Error Boundary(错误边界) 机制,允许开发者在组件层级中优雅地捕获渲染期间的错误,并展示降级 UI,而不是让整个页面挂掉。
错误捕获在 React 中分为两大类场景:
- 渲染阶段的错误:组件 render、生命周期方法、构造函数中抛出的异常,由 Error Boundary 捕获
- 非渲染阶段的错误:事件处理函数、异步代码、服务端渲染中的异常,需要传统的 try-catch 等方式处理
二、Error Boundary 错误边界
基本实现
Error Boundary 是一个 class 组件,通过实现 getDerivedStateFromError 和 componentDidCatch 两个生命周期来捕获子组件树中的错误:
两个生命周期的分工:
使用方式
Error Boundary 的局限性
Error Boundary 无法捕获以下场景的错误:
- 事件处理函数中的错误——事件回调不在 React 渲染流程中
- 异步代码——如
setTimeout、Promise回调 - 服务端渲染——SSR 阶段没有 commit 过程
- Error Boundary 自身抛出的错误
三、事件处理与异步错误捕获
事件处理函数中的 try-catch
全局未捕获错误监听
四、react-error-boundary 库
社区库 react-error-boundary 提供了更完善的错误边界方案,支持函数式用法和重置机制:
在事件处理中手动触发错误边界
useErrorBoundary hook 可以将事件处理或异步代码中的错误抛给最近的 Error Boundary:
五、细粒度错误边界策略
实际项目中,不应只在根组件放一个 Error Boundary,而是根据功能模块设置多层错误边界:
这种策略的好处:
- 隔离影响范围:某个模块出错不影响其他模块正常使用
- 差异化降级:核心功能显示友好提示,非核心功能(如统计组件)静默失败
- 路由级边界:每个路由页面一个 Error Boundary,页面间错误互不影响
六、错误上报与监控
结构化的错误信息应包含:错误消息、调用栈、React 组件栈、页面 URL、用户环境、时间戳等。
七、React 19 的错误处理改进
React 19 对错误处理做了显著改进:
改进的错误报告
React 19 不再重复打印错误日志。之前版本中,createRoot 下的渲染错误会先被 console.error 打印一次,然后 componentDidCatch 再打印一次。React 19 统一为一次有意义的错误输出。
函数组件错误边界的未来
目前 Error Boundary 只能用 class 组件实现,因为依赖 getDerivedStateFromError 和 componentDidCatch 这两个类生命周期。React 团队已在讨论为函数组件提供等价能力,可能通过新的 hook 或 API 实现。在此之前,react-error-boundary 库是最佳替代方案。
onCaughtError 与 onUncaughtError
React 19 在 createRoot 配置中新增了错误回调:
八、总结
最佳实践:
- 在应用的关键层级设置多个 Error Boundary,做到错误隔离
- 使用
react-error-boundary获得更好的开发体验 - 建立完善的错误上报机制,结合 Sentry 等监控工具
- 为用户提供有意义的错误提示和重试选项
- 关注 React 19 的错误处理新特性,及时升级