React Native应用全局错误捕获最优方案咨询
React Native 全局错误捕获最优方案
React Native的错误分JS层、Native原生层、组件渲染层三类,要实现全量捕获得分层处理,下面是落地性极强的方案:
1. JS 全局错误捕获
React Native 没有浏览器环境的window.onerror,官方推荐用ErrorUtils捕获JS层面的未处理错误,同时还要处理Promise未捕获的拒绝:
// 在项目入口文件(如index.js)配置 import { ErrorUtils } from 'react-native'; // 捕获同步/异步JS错误 const originalGlobalHandler = ErrorUtils.getGlobalHandler(); ErrorUtils.setGlobalHandler((error, isFatal) => { // 这里可做错误上报、本地日志存储 console.error(`JS全局错误 ${isFatal ? '(致命)' : ''}:`, error); // 保留原有全局处理逻辑,避免吞掉错误 if (originalGlobalHandler) { originalGlobalHandler(error, isFatal); } }); // 捕获Promise未处理的拒绝 global.addEventListener('unhandledrejection', (event) => { console.error('Promise未捕获拒绝:', event.reason); // 可选:阻止默认行为,避免控制台重复输出 event.preventDefault(); });
2. 组件渲染层错误捕获(Error Boundary)
针对组件渲染时抛出的错误(比如渲染null/undefined属性、数组越界),用React官方的Error Boundary组件包裹根组件或关键业务组件,避免单个组件崩溃导致整个App挂掉:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // 更新state,展示降级UI return { hasError: true }; } componentDidCatch(error, errorInfo) { // 上报错误详情 console.error('组件渲染错误:', error, errorInfo); } render() { if (this.state.hasError) { // 自定义降级UI,比如错误提示页 return <Text>抱歉,页面出现错误,请稍后重试</Text>; } return this.props.children; } } // 在根组件中使用 export default function App() { return ( <ErrorBoundary> {/* 你的App核心内容 */} <NavigationContainer>...</NavigationContainer> </ErrorBoundary> ); }
注意:Error Boundary 无法捕获异步错误、事件回调中的错误,这类错误需靠JS全局捕获处理。
3. Native 原生层错误捕获
原生层的崩溃(比如iOS的OC/Swift错误、Android的Java/Kotlin错误)需要在原生代码中配置:
iOS 端
在AppDelegate.m(或AppDelegate.swift)中添加全局异常捕获:
// AppDelegate.m #import <UIKit/UIKit.h> #import <React/RCTBridge.h> void uncaughtExceptionHandler(NSException *exception) { // 收集错误信息:异常原因、调用栈 NSString *errorMsg = [NSString stringWithFormat:@"Native崩溃: %@\n调用栈:\n%@", exception.reason, [exception callStackSymbols]]; NSLog(@"%@", errorMsg); // 可写入本地日志或通过原生模块上报给JS层 } @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 设置全局异常处理器 NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); // ...其他初始化代码 return YES; } @end
Android 端
在MainApplication.java中配置全局异常处理器:
// MainApplication.java import android.os.Handler; import android.os.Looper; import android.util.Log; import android.widget.Toast; public class MainApplication extends Application implements ReactApplication { @Override public void onCreate() { super.onCreate(); // 设置全局未捕获异常处理器 Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { // 收集错误信息 String errorMsg = "Native崩溃: " + throwable.getMessage() + "\n" + Log.getStackTraceString(throwable); Log.e("NativeError", errorMsg); // 可选:通过Toast提示用户,或写入本地文件 new Handler(Looper.getMainLooper()).post(() -> { Toast.makeText(getApplicationContext(), "应用出现错误", Toast.LENGTH_LONG).show(); }); }); // ...其他初始化代码 } }
4. 额外优化建议
- 日志分级处理:开发环境直接打印控制台,生产环境将错误日志写入本地文件,待App下次启动时批量上报到服务器
- 区分错误优先级:致命错误(导致App崩溃)优先上报,非致命错误可延迟上报
- 容错上报逻辑:错误上报代码本身要做容错,比如网络请求失败时不要抛出新错误,避免恶性循环
- 监控工具辅助:可以集成成熟的错误监控工具,这类工具能自动收集用户设备、App版本、错误上下文等多维度信息,降低排查成本
内容的提问来源于stack exchange,提问作者Tavojavi
相关产品推荐
相关产品推荐

