how to catch uncaught exception (globally) in react native
Asked Answered
O

5

33

Does anyone know what is the best way to catch all uncaught exception (globally) so that I can send a crash report back to the server? I don't seem to be able to find any information on the react native docs or on github.

Orangutan answered 18/6, 2015 at 14:35 Comment(1)
Why are you trying to do this, exactly?Manlove
S
32

You could possibly override the exception logging that React Native uses for development:

ErrorUtils.setGlobalHandler(function() {
// your handler here
});

https://github.com/facebook/react-native/blob/522fd33d6f3c8fb339b0dde35b05df34c1233306/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js#L46

You may then need to write some Obj-C which you expose to JS, depending on your exact requirements.

Soil answered 18/6, 2015 at 16:38 Comment(0)
O
14

This is how I'd do it:

Step 1: We intercept react-native error handler like so:

//intercept react-native error handling
if (ErrorUtils._globalHandler) {
  this.defaultHandler = ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler() || ErrorUtils._globalHandler;
  ErrorUtils.setGlobalHandler(this.wrapGlobalHandler);  //feed errors directly to our wrapGlobalHandler function
}

Step 2: Now our wrapGlobalHandler gets called whenever theres an unhandled error. So do anything you want with the error within this function.

Then do something with the error:

async function wrapGlobalHandler(error, isFatal){

    const stack = parseErrorStack(error);

    //do anything with the error here

    this.defaultHandler(error, isFatal);  //after you're finished, call the defaultHandler so that react-native also gets the error
}

Full code here:

import stacktraceParser from 'stacktrace-parser';


const parseErrorStack = (error) => {
    if (!error || !error.stack) {
        return [];
    }
    return Array.isArray(error.stack) ? error.stack :
    stacktraceParser.parse(error.stack);
};


// intercept react-native error handling
if (ErrorUtils._globalHandler) {
    this.defaultHandler = (ErrorUtils.getGlobalHandler
        && ErrorUtils.getGlobalHandler())
        || ErrorUtils._globalHandler;
    ErrorUtils.setGlobalHandler(this.wrapGlobalHandler); // feed errors directly to our wrapGlobalHandler function
}

async function wrapGlobalHandler(error, isFatal) {

    const stack = parseErrorStack(error);

    //do anything with the error here

    this.defaultHandler(error, isFatal);  //after you're finished, call the defaultHandler so that react-native also gets the error
}

Thats it!

On answered 4/7, 2016 at 18:35 Comment(8)
May I ask what is parseErrorStack function supposed to do? when I try to log the error param on chrome I get some output, but on react-native I only get an empty objectCabinetwork
Hey ospfranco, I just added the full code, sorry for the delay.On
@On could you please explain where should I use this code?Robrobaina
@Ansal Ali you can use it anywhere on your code, and it should work. Ideally I'd use it on the initialization file of the app. (Before the first component loads).On
@Ansal Ali take a look at this file: github.com/SudoPlz/react-native-bugsnag/blob/master/lib/… It might help you understand what you're doing differently. I was using that code for a long time and it worked fine.On
@On Can you provide example how to call from app initialization?Shred
Sorry I can't do that, but this should give you ALL you need: github.com/bugsnag/bugsnag-react-native/blob/… After that just calling this.handleUncaughtErrors(); should be enough.On
Does this catch errors produced by native modules too or just JS errors?Didactics
I
6

You can try https://github.com/master-atul/react-native-exception-handler.

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.

Inga answered 2/12, 2017 at 6:6 Comment(0)
D
4

There is a native way.

RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_scriptURL
                                      moduleProvider:^{
                                        id<RCTExceptionsManagerDelegate> customDelegate = ...
                                        return @[[RCTExceptionsManager initWithDelegate:customDelegate];
                                      }
                                       launchOptions:nil];

Just put your report logic in the customDelegate.

Deva answered 19/6, 2015 at 10:33 Comment(2)
If you had the respective solution for Android that would turn out super helpful for me.Tarkington
@Tarkington you can use Thread.setDefaultUncaughtExceptionHandler in AndroidBreakfast
S
3

There's now react-native-error-reporter, which pretty much does the trick in a very simple way:

npm i react-native-error-reporter --save
rnpm link

Then add this lines to your code:

import ErrorReporter from 'react-native-error-reporter';
ErrorReporter.init("[email protected]", "My App's Crash Report");

In case you're using Redux, you might wanna try redux-catch middleware.

Samarskite answered 2/7, 2016 at 4:12 Comment(1)
Better than react-native-error-reporter there's now react-native-exception-handler which gives you an interface to the user AND a way to catch native errors. github.com/master-atul/react-native-exception-handlerBibliomania

© 2022 - 2024 — McMap. All rights reserved.