Reactotron: Unhandled promise rejection tracking in React Native

Created on 30 Apr 2018  ·  9Comments  ·  Source: infinitered/reactotron

Problem

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.

Solution

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.

Issues

Don't use console.tron

Probably should use a normal import statement since not everyone does that console hanging trick.

Minimum Version

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.

Integrate with 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?

Verify it doesn't break anything else?

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? 🤷‍♂️ 🤞

Field Testing

Anyone interested in trying this out on their project?

discussion react-native

All 9 comments

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:

  • attaching to console
  • not caring about shipping to prod
  • hooking up the network tracking and promise tracking
  • basically all features on by default
  • with the expectation that this will break in future versions once the internals of React Native change. But until that day... it will be glorious!

.useReactNativeYOLO()

Tracking #578

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Anahkiasen picture Anahkiasen  ·  5Comments

skellock picture skellock  ·  4Comments

dhruwal picture dhruwal  ·  3Comments

fkereki picture fkereki  ·  3Comments

sylar picture sylar  ·  4Comments