Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
react-native-exception-handler
Advanced tools
A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions.
A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions. The module helps prevent abrupt crashing of RN Apps without a graceful message to the user.
In the current scenario:
In DEV mode , you get a RED Screen error pointing your errors.
In Bundled mode , the app just quits without any prompt !
🙄To tackle this we register a global error handler that could be used to for example:
V2 of this module now supports catching Unhandled Native Exceptions also along with the JS Exceptions ✌🏻🍻 There are NO breaking changes. So its safe to upgrade from v1 to v2. So there is no reason not to 😉.
Example repo can be found here: *https://github.com/master-atul/react-native-exception-handler-example *
In DEV MODE
In BUNDLED MODE
With react-native-exception-handler in BUNDLED MODE
yarn add react-native-exception-handler
or
npm i react-native-exception-handler --save
react-native link react-native-exception-handler
Libraries
➜ Add Files to [your project's name]
node_modules
➜ react-native-exception-handler
and add ReactNativeExceptionHandler.xcodeproj
libReactNativeExceptionHandler.a
to your project's Build Phases
➜ Link Binary With Libraries
Cmd+R
)<android/app/src/main/java/[...]/MainApplication.java
import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerPackage;
to the imports at the top of the filenew ReactNativeExceptionHandlerPackage()
to the list returned by the getPackages()
methodandroid/settings.gradle
:
include ':react-native-exception-handler'
project(':react-native-exception-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-exception-handler/android')
android/app/build.gradle
:
compile project(':react-native-exception-handler')
Lets introduce you to the type of errors in a RN app.
Errors produced by your Javascript code (includes all your react code). We will refer to these errors as JS_Exceptions going forward.
Errors produced by Native Modules. We will refer to these as Native_Exceptions going forward.
Unhandled exceptions leave the app in a critical state.
In case of JS_Exceptions you can catch these unhandled exceptions and perform tasks like show alerts or popups, do cleanup or even hit an API to inform the dev teams before closing the app.
In case of Native_Exceptions it becomes much worse. While you can catch these unhandled exceptions and perform tasks like cleanup or logout or even hit an API to inform the dev teams before closing the app, you CANNOT show a JS alert box or do any UI stuff via JS code. This has to be done via the native methods provided by this module in the repective NATIVE codebase for iOS and android. The module does provide default handlers though :P. So you will get default popups incase of errors. Obviously you can customise them. See CUSTOMIZATION section.
To catch JS_Exceptions
import {setJSExceptionHandler, getJSExceptionHandler} from 'react-native-exception-handler';
.
.
// registering the error handler (maybe u can do this in the index.android.js or index.ios.js)
setJSExceptionHandler((error, isFatal) => {
// This is your custom global error handler
// You do stuff like show an error dialog
// or hit google analytics to track crashes
// or hit a custom api to inform the dev team.
});
// getJSExceptionHandler gives the currently set JS exception handler
const currentHandler = getJSExceptionHandler();
To catch Native_Exceptions
import {setNativeExceptionHandler} from 'react-native-exception-handler';
setNativeExceptionHandler((exceptionString) => {
// This is your custom global error handler
// You do stuff likehit google analytics to track crashes.
// or hit a custom api to inform the dev team.
//NOTE: alert or showing any UI change via JS
//WILL NOT WORK in case of NATIVE ERRORS.
});
It is recommended you set both the handlers.
See the examples to know more
In case of setJSExceptionHandler
you can do everything that is possible. Hence there is not much to customize here.
const errorHandler = (error, isFatal) => {
// This is your custom global error handler
// You do stuff like show an error dialog
// or hit google analytics to track crashes
// or hit a custom api to inform the dev team.
})
//Second argument is a boolean with a default value of false if unspecified.
//If set to true the handler to be called in place of RED screen
//in development mode also.
setJSExceptionHandler(errorHandler, true);
By default whenever a Native_Exceptions occurs if you have used setNativeExceptionHandler
, along with the callback specified you would see a popup (this is the default native handler set by this module).
In Android and iOS you will see something like
Modifying Android Native Exception handler UI (NATIVE CODE HAS TO BE WRITTEN) recommended that you do this in android studio
android/app/src/main/java/[...]/
. For example lets say CustomErrorDialog.javaandroid/app/src/main/java/[...]/MainApplication.java
import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerModule;
import <yourpackage>.YourCustomActivity; //This is your CustomErrorDialog.java
...
...
...
public class MainApplication extends Application implements ReactApplication {
...
...
@Override
public void onCreate() {
....
....
....
ReactNativeExceptionHandlerModule.replaceErrorScreenActivityClass(YourCustomActivity.class); //This will replace the native error handler popup with your own custom activity.
}
Modifying iOS Native Exception handler UI (NATIVE CODE HAS TO BE WRITTEN) recommended that you do this in XCode
Unlike Android, in the case of iOS, there is no way to restart the app if it has crashed. Also, during a Native_Exceptions the UI becomes quite unstable since the exception occured on the main UI thread. Hence, none of the click or press handlers would work either.
Keeping in mind of these, at the most we can just show the user a dialog and inform the user to reopen the app.
If you noticed the default native exception popup does exactly that. To customize the UI for the popup.
AppDelegate.m
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
//Add the header file
#import "ReactNativeExceptionHandler.h"
...
...
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
...
[ReactNativeExceptionHandler replaceNativeExceptionHandlerBlock:^(NSException *exception, NSString *readeableException){
// THE CODE YOU WRITE HERE WILL REPLACE THE EXISTING NATIVE POPUP THAT COMES WITH THIS MODULE.
//We create an alert box
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:@"Critical error occurred"
message: [NSString stringWithFormat:@"%@\n%@",
@"Apologies..The app will close now \nPlease restart the app\n",
readeableException]
preferredStyle:UIAlertControllerStyleAlert];
// We show the alert box using the rootViewController
[rootViewController presentViewController:alert animated:YES completion:nil];
// THIS IS THE IMPORTANT PART
// By default when an exception is raised we will show an alert box as per our code.
// But since our buttons wont work because our click handlers wont work.
// to close the app or to remove the UI lockup on exception.
// we need to call this method
// [ReactNativeExceptionHandler releaseExceptionHold]; // to release the lock and let the app crash.
// Hence we set a timer of 4 secs and then call the method releaseExceptionHold to quit the app after
// 4 secs of showing the popup
[NSTimer scheduledTimerWithTimeInterval:4.0
target:[ReactNativeExceptionHandler class]
selector:@selector(releaseExceptionHold)
userInfo:nil
repeats:NO];
// or you can call
// [ReactNativeExceptionHandler releaseExceptionHold]; when you are done to release the UI lock.
}];
...
...
...
return YES;
}
@end
What is this [ReactNativeExceptionHandler releaseExceptionHold];
?
In case of iOS we lock the UI thread after we show our popup to prevent the app from closing.
Hence once we are done showing the popup we need to close our app after some time.
But since our buttons wont work as our click handlers wont work (explained before).
To close the app or to remove the UI lockup on exception, we need to call this method
[ReactNativeExceptionHandler releaseExceptionHold];
Hence we set a timer of 4 secs and then call the method releaseExceptionHold to quit the app after 4 secs of showing the popup
[NSTimer scheduledTimerWithTimeInterval:4.0
target:[ReactNativeExceptionHandler class]
selector:@selector(releaseExceptionHold)
userInfo:nil
repeats:NO];
This example shows how to use this module show a graceful bug dialog to the user on crash and restart the app when the user presses ok !
import {Alert} from 'react-native';
import RNRestart from 'react-native-restart';
import {setJSExceptionHandler} from 'react-native-exception-handler';
const errorHandler = (e, isFatal) => {
if (isFatal) {
Alert.alert(
'Unexpected error occurred',
`
Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message}
We will need to restart the app.
`,
[{
text: 'Restart',
onPress: () => {
RNRestart.Restart();
}
}]
);
} else {
console.log(e); // So that we can see it in the ADB logs in case of Android if needed
}
};
setJSExceptionHandler(errorHandler);
setNativeExceptionHandler((errorString) => {
//You can do something like call an api to report to dev team here
...
...
// When you call setNativeExceptionHandler, react-native-exception-handler sets a
// Native Exception Handler popup which supports restart on error in case of android.
// In case of iOS, it is not possible to restart the app programmatically, so we just show an error popup and close the app.
// To customize the popup screen take a look at CUSTOMIZATION section.
});
This example shows how to use this module to send global errors to the dev team and show a graceful bug dialog to the user on crash !
import {Alert} from 'react-native';
import {BackAndroid} from 'react-native';
import {setJSExceptionHandler} from 'react-native-exception-handler';
const reporter = (error) => {
// Logic for reporting to devs
// Example : Log issues to github issues using github apis.
console.log(error); // sample
};
const errorHandler = (e, isFatal) => {
if (isFatal) {
reporter(e);
Alert.alert(
'Unexpected error occurred',
`
Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message}
We have reported this to our team ! Please close the app and start again!
`,
[{
text: 'Close',
onPress: () => {
BackAndroid.exitApp();
}
}]
);
} else {
console.log(e); // So that we can see it in the ADB logs in case of Android if needed
}
};
setJSExceptionHandler(errorHandler);
setNativeExceptionHandler((errorString) => {
//You can do something like call an api to report to dev team here
//example
// fetch('http://<YOUR API TO REPORT TO DEV TEAM>?error='+errorString);
//
});
More Examples can be found in the examples folder
This is specifically occuring when you use wix library for navigation along with react-native-exception-handler. Whenever an error occurs, it will recreate the application above the crash screen.
Fix:
You need to set second parametera as false while calling setNativeExceptionHandler. The second parameter is an android specific field which stands for forceQuitOnError. When set to false it doesnt quit the app forcefully on error. In short :
Credit goes to Gustavo Fão Valvassori
setNativeExceptionHandler(nativeErrorCallback, false);
To make sure this module works. You can generate a native exception using the module rn-test-exception-handler
.
https://github.com/master-atul/rn-test-exception-handler
rn-test-exception-handler
module does only one thing. It raises a Native_Exceptions.
This will help you to verify your customizations or functionality of this module.
Peace ! ✌🏻🍻
FAQs
A react native module that lets you to register a global error handler that can capture fatal/non fatal uncaught exceptions.
The npm package react-native-exception-handler receives a total of 39,507 weekly downloads. As such, react-native-exception-handler popularity was classified as popular.
We found that react-native-exception-handler demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.