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.
My suggestion is to wrap every navigation screen in your Application with a react-error-boundary component and provide a fallback component to Make sure the user knows what's happening, and maybe you can recover the screen with a rerender. The best way to do it is to create an Errorhandler component like the following.
Error handling with Error Boundaries — For class components. Error boundaries are the most straightforward and effective way to handle errors that occur within your React components. You can create an error boundary component by including the life cycle method componentDidCatch(error, info) if you use class component.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With