React Native (coming soon)
Overview

React Native

⚠️

Not available yet. TracePath does not publish a React Native package. There is nothing to install, and the @tracepath scope on npm belongs to an unrelated third party — do not run an install command against it. This page describes the planned integration. Email [email protected] to hear when it ships.

The planned React Native package will be plain JavaScript — no native modules, no pod install, no Gradle changes — so it works in Expo Go, in bare React Native CLI projects and in EAS builds alike.

What it will capture

Mounting the provider at your app's root initializes the SDK once and installs:

  • Uncaught throws on the JS thread, through React Native's global error handler. The red-box dev overlay still appears; the previous handler is chained, not replaced.
  • Render errors: the provider doubles as an error boundary, capturing exceptions thrown during render or in lifecycle methods and re-throwing them so the app behaves exactly as it would without TracePath.
  • fetch calls, recorded with method, URL, status, duration and byte counts.
  • XMLHttpRequest calls — React Native polyfills XHR, and fetch is implemented on top of it on some platforms, so both paths are covered.
  • Console output: console.{debug,log,info,warn,error} mirrored into the rolling log buffer that rides along the next exception.

Unhandled promise rejections will not be captured. React Native routes them to its own exceptions manager, and only in dev builds, never through the global error handler, so the SDK never sees them. Catch them yourself and capture explicitly. This is the single biggest gap to design around.

No screen recording. Unlike the browser SDK, this package will not record the screen: the rrweb recorder is deliberately absent, since nothing in the bundle should reach for a DOM that does not exist.

Distributed tracing is opt-in here

The browser SDK infers "same origin" from window.location.origin and instruments only those requests. React Native has no such origin, so trace-header injection will be opt-in: you list your own backend hosts, as exact hostnames or regular expressions matched against the URL host, and only those requests carry the header. Include the port when your URLs have one.

XMLHttpRequest calls are recorded as network actions but do not receive the header, so route traffic you want linked through fetch. See Distributed Tracing for the backend half, which works today.

Navigation

React Native has no window.history to instrument, so navigation actions are recorded by calling the SDK from whatever navigation library you use — a state-change callback on React Navigation's container, or an effect keyed on the current pathname with Expo Router. Nothing is recorded automatically.

Attributes

Each captured exception will carry an attributes map built from three layers, per-call winning over the global scope, which wins over device info.

Device info is stamped automatically and needs no native module, but only the values reachable without one: the device locale and the JS engine. Other keys — OS name and version, screen resolution and density — are readable from React Native's own modules, and the SDK will expose a setter so you can pass them in yourself alongside anything from expo-device or a device-info library you already have. The key names mirror what the Flutter and Android SDKs emit, so the dashboard renders them consistently across platforms.

Global scope is for things tied to the user, tenant or app state: user id, organization id, build channel, feature flags, A/B bucket. It will be settable declaratively from a component or hook — diffing against the previous map, removing owned keys on unmount — and imperatively from auth listeners and background tasks.

Attribute values must be strings: the ingest endpoint types them as a string map and rejects the whole upload with 400 Bad Request otherwise, and the SDK re-queues a rejected batch, so one bad value blocks every later event from that app instance.

Symbolication for release builds

A debug build gives readable stack traces for free. A release build does not: Metro minifies the JavaScript into one bundle and Hermes compiles it to bytecode, so every production frame is an offset into index.android.bundle or main.jsbundle with no function names.

The source map upload endpoint works today and is documented at Source Maps. Two things are worth setting up now, because they are entirely on your side of the line:

  • Emit the maps. Android already does: the React Native Gradle plugin passes -output-source-map to Hermes by default, and a release build writes the map under android/app/build/generated/sourcemaps/react/release/. iOS needs one line added to the Bundle React Native code and images build phase in Xcode:

    export SOURCEMAP_FILE="$(pwd)/../main.jsbundle.map"

    After an archive build the map is then at ios/main.jsbundle.map. Both paths have moved between React Native versions; if yours is not there, search the build output for *.bundle.map.

  • Keep the filename. TracePath matches a map to a frame by filename, so a map for index.android.bundle must be uploaded as index.android.bundle.map. curl -F sends the basename of the local path, which is what you want.

Uploaded maps simply have nothing to resolve until the SDK ships and starts sending frames.

Planned platform support

PlatformError trackingScreen recording
iOS (RN >= 0.72)YesNo
Android (RN >= 0.72)YesNo
Expo (SDK 49+)Yes, including Expo GoNo
Web, via React Native WebYesNo

What to do today

The backend your app talks to can be instrumented now with OpenTelemetry, and synthetic monitors can watch your API from the outside with no code at all. For native-only apps, Android and iOS are planned separately; for Flutter, see Flutter.