When a promise isn't caught within the React Native ecosystem, it bubbles up without a stack trace that goes thru the sourcemap resolving gauntlet.
We're left with a error message that is really goofy.
Several versions ago (mid 40's? maybe?), they introduced a way to hook this. Surprisingly they don't do anything with this.
So let's hook that event and throw it over the wire to Reactotron.
Here's a proof of concept that works:
// reactotron-unhanded-rejections.ts
// pass all unhandled promise rejections through reactotron
if (__DEV__) {
// reach horribly into the bowels of react native
const rejectionTracking = require("promise/setimmediate/rejection-tracking")
// if we have it
if (rejectionTracking && rejectionTracking.enable) {
// register for rejection tracking
rejectionTracking.enable({
allRejections: true,
onUnhandled: (id, error) => {
console.tron && console.tron.reportError(error)
},
onHandled: () => {},
})
}
}
Now our stacktraces will show up & be resolved properly with sourcemapp-resolved lookups.
console.tronProbably should use a normal import statement since not everyone does that console hanging trick.
With Reactotron 2.0 we need to pick a minimum version. I'm thinking 54 (only because that's my current project)... but whatever we settle on, we need to make sure this is tested since it's an internal file.
It might be great just to figure out what version it came with, just so we know.
trackGlobalErrors?Should this be baked into the trackGlobalErrors plugin (reactotron-react-native only)? On by default, but provide a way to opt out?
Do that make sense?
One thing that makes me squirrely about reaching into internals of React Native is that we're clobbering something else of theirs out of the box.
I felt that way with network tracking and error swizzling... now here's a 3rd? Everything seems to work though? 🤷♂️ 🤞
Anyone interested in trying this out on their project?
we're clobbering something else of theirs out of the box
Are you saying we _might_ clobber something of theirs, or _are_ for sure?
might.
Everything seems to work though
Ultimately these are private apis. And it could all explode at any minute. So far we're good! :shipit:
I like this idea but I think the most important part is that we should make it opt-in vs opt-out. Reason being is since this isn't like the global error tracking that still calls the original function it (as you say...) clobbers anything that might be there (or will be there in the future).
Opt-in makes sense. Might raise more issues where the answer is "turn on promise rejection trackign" but at least the mechanism is there.
I'm ok with opt-in. We might want to switch our network tracking to opt-in as well, since you can only have 1 listener too.
@skellock honestly... probably. We would have to wrap that up in a breaking change though.
.useReactNative() would be no-funny stuff mode
.useReactNative({ ...opts }) would be how you turn specific things on
And .useReactNativeRideOrDie() would be full-on madness including:
.useReactNativeYOLO()
Tracking #578