Package Exports
- react-native-global-exception-handler
- react-native-global-exception-handler/package.json
Readme
⚠️ This is a fork of react-native-exception-handler. All credit goes to the original author
react-native-global-exception-handler
A modern React Native library that provides comprehensive global error handling for both JavaScript and native exceptions. Built with the latest React Native architecture including TurboModules support and cross-platform compatibility.
The library helps prevent abrupt app crashes by providing graceful error handling and customizable recovery options.
Key Features
- 🔥 Modern Architecture: Built with TurboModules for React Native 0.68+
- 📱 Cross-Platform: Full iOS and Android support
- 🎯 Dual Exception Handling: Catches both JS and native exceptions
- 🔧 Highly Customizable: Configurable options for different platforms
- 🚀 Crash Simulation: Built-in crash testing for development
- 🎨 Custom Error UI: Platform-specific error screens with restart functionality
- ⚡ TypeScript Support: Full TypeScript definitions included
What This Solves
In the current React Native ecosystem:
In DEV mode: You get a RED screen error pointing to your errorsIn RELEASE mode: The app just quits without any user feedback! 🙄
This library provides:
- Graceful Error Handling: Show user-friendly error messages instead of crashes
- Crash Reporting: Send error reports to your analytics/monitoring service
- App Recovery: Built-in restart functionality for better user experience
- Development Tools: Crash simulation for testing error handling
Demo
| iOS | Android |
|---|---|
Installation
npm install react-native-global-exception-handleror
yarn add react-native-global-exception-handlerFor React Native 0.68+
This library uses TurboModules and auto-linking, so no additional setup is required for modern React Native versions.
For React Native < 0.68
Please use react-native-exception-handler (the original library) for older React Native versions.
Basic Usage
JavaScript Exception Handling
import { setJSExceptionHandler } from 'react-native-global-exception-handler';
// Basic setup
setJSExceptionHandler((error, isFatal) => {
console.log('JS Exception:', error);
if (isFatal) {
// Handle fatal errors - maybe show restart dialog
} else {
// Handle non-fatal errors - maybe just log them
}
});
// Advanced setup with dev mode control
setJSExceptionHandler(
(error, isFatal) => {
// Your error handler
},
true // Allow in dev mode (shows instead of RedBox)
);Native Exception Handling
import { setNativeExceptionHandler } from 'react-native-global-exception-handler';
// Basic setup with default options
setNativeExceptionHandler((errorString) => {
console.log('Native Exception:', errorString);
// Send to crash reporting service
});
// Advanced setup with platform-specific options
setNativeExceptionHandler(
(errorString) => {
console.log('Native Exception:', errorString);
},
{
forceAppToQuit: true, // Android: Force app to quit after error
callPreviouslyDefinedHandler: false // Call previous exception handler
}
);
// Legacy API (still supported)
setNativeExceptionHandler(
(errorString) => { /* handler */ },
true, // forceAppToQuit (Android)
false // executeDefaultHandler (iOS)
);API Reference
setJSExceptionHandler(handler, allowInDevMode?)
Registers a global JavaScript exception handler.
Parameters:
handler: (error: Error, isFatal: boolean) => void- The exception handler functionallowInDevMode?: boolean- Whether to show handler in dev mode (default: false)
setNativeExceptionHandler(handler, options?)
Registers a global native exception handler with platform-specific options.
Parameters:
handler: (errorString: string) => void- The exception handler functionoptions?: ExceptionHandlerOptions- Platform-specific configuration
Options:
interface ExceptionHandlerOptions {
callPreviouslyDefinedHandler?: boolean; // Call previous handler (default: false)
forceAppToQuit?: boolean; // Android: Force app quit (default: true)
}simulateNativeCrash(crashType?)
Simulates a native crash for testing purposes (DEV mode only).
Crash Types:
'nsexception'- Standard exception (default)'array_bounds'- Array bounds exception'invalid_argument'- Invalid argument exception'memory_access'- Memory access violation'abort'- Abort signal'stack_overflow'- Stack overflow'internal_inconsistency'- Internal inconsistency'malloc_error'- Memory allocation error'sigill'- Illegal instruction'sigbus'- Bus error
import { simulateNativeCrash } from 'react-native-global-exception-handler';
// Simulate different crash types for testing
simulateNativeCrash('memory_access');
simulateNativeCrash('array_bounds');getJSExceptionHandler()
Returns the currently set JavaScript exception handler.
Examples
Complete Error Handling Setup
import {
setJSExceptionHandler,
setNativeExceptionHandler,
simulateNativeCrash
} from 'react-native-global-exception-handler';
import { Alert, Platform } from 'react-native';
// Setup JS exception handling
setJSExceptionHandler((error, isFatal) => {
if (isFatal) {
Alert.alert(
'Unexpected Error',
`A fatal error occurred: ${error.name}\n${error.message}\n\nThe app will need to restart.`,
[{
text: 'Restart App',
onPress: () => {
// Restart logic here
}
}]
);
} else {
// Log non-fatal errors
console.warn('Non-fatal JS error:', error);
}
}, false);
// Setup native exception handling
setNativeExceptionHandler(
(errorString) => {
// Send to crash reporting
console.log('Native error occurred:', errorString);
// You can send to services like:
// - Crashlytics
// - Sentry
// - Bugsnag
// - Custom analytics endpoint
},
{
forceAppToQuit: Platform.OS === 'android', // Android specific
callPreviouslyDefinedHandler: false // iOS specific
}
);Testing Error Handling
import { simulateNativeCrash } from 'react-native-global-exception-handler';
// Test different crash scenarios
const testCrashes = () => {
// Test JS error
throw new Error('Test JS Error');
};
const testNativeCrash = () => {
simulateNativeCrash('array_bounds');
};
// In your component
<Button title="Test JS Error" onPress={testCrashes} />
<Button title="Test Native Crash" onPress={testNativeCrash} />Customization
Custom Native Error Screen (Android)
You can customize the native error screen that appears when a native exception occurs on Android:
Method 1: Custom Exception Handler Interface
// In your MainApplication.kt
import com.globalexceptionhandler.GlobalExceptionHandlerModule
import com.globalexceptionhandler.NativeExceptionHandlerIfc
class MainApplication : Application(), ReactApplication {
override fun onCreate() {
super.onCreate()
// Set custom native exception handler
GlobalExceptionHandlerModule.setNativeExceptionHandler(object : NativeExceptionHandlerIfc {
override fun handleNativeException(
thread: Thread,
throwable: Throwable,
originalHandler: Thread.UncaughtExceptionHandler?
) {
// Custom handling logic
// - Send to analytics
// - Show custom UI
// - Clean up resources
}
})
}
}Method 2: Custom Error Activity
// Create CustomErrorActivity.kt
class CustomErrorActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Your custom error UI
setContentView(R.layout.custom_error_layout)
}
}
// In MainApplication.kt
override fun onCreate() {
super.onCreate()
GlobalExceptionHandlerModule.replaceErrorScreenActivityClass(
CustomErrorActivity::class.java
)
}Custom Native Error Screen (iOS)
For iOS customization, modify your AppDelegate.m:
#import "GlobalExceptionHandler.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Your existing setup...
// Custom native exception handler
[GlobalExceptionHandler replaceNativeExceptionHandlerBlock:^(NSException *exception, NSString *readeableException) {
// Create custom alert
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:@"App Error"
message:[NSString stringWithFormat:@"An unexpected error occurred.\n%@", readeableException]
preferredStyle:UIAlertControllerStyleAlert];
// Present the alert
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
// Auto-close after 4 seconds
[NSTimer scheduledTimerWithTimeInterval:4.0
target:[GlobalExceptionHandler class]
selector:@selector(releaseExceptionHold)
userInfo:nil
repeats:NO];
}];
return YES;
}Integration with Analytics Services
Crashlytics
import crashlytics from '@react-native-firebase/crashlytics';
setJSExceptionHandler((error, isFatal) => {
crashlytics().recordError(error);
});
setNativeExceptionHandler((errorString) => {
crashlytics().log(errorString);
});Sentry
import * as Sentry from '@sentry/react-native';
setJSExceptionHandler((error, isFatal) => {
Sentry.captureException(error);
});
setNativeExceptionHandler((errorString) => {
Sentry.captureMessage(errorString);
});Platform Differences
iOS
- Cannot restart app programmatically after native crash
- UI becomes unstable during native exceptions
- Best practice: Show informative message and ask user to restart
- Exception handler must call
releaseExceptionHold()to close app
Android
- Can restart app after native crash
- More stable during native exceptions
- Built-in restart functionality in default error screen
- More customization options available
Troubleshooting
TurboModule Issues
If you encounter TurboModule binding issues:
- Ensure you're using React Native 0.68+
- Clear metro cache:
npx react-native start --reset-cache - Clean and rebuild:
cd android && ./gradlew clean && cd .. && npx react-native run-android
Android Build Issues
If you encounter Android build issues:
- Check that your
android/build.gradlehas the correct Kotlin version - Ensure your target SDK is compatible
- Try cleaning:
cd android && ./gradlew clean
Contributing
See the contributing guide to learn how to contribute to the repository and the development workflow.
License
MIT
Made with ❤️ for the React Native community