npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tracewayapp/react-native

v1.0.7

Published

Traceway React Native SDK — error tracking with last-10s session context for iOS, Android and Expo apps

Readme

Traceway React Native SDK

Error tracking for React Native and Expo apps. Capture exceptions with full stack traces, plus the last ~10 seconds of console logs, HTTP calls, navigation transitions, and custom breadcrumbs — automatically.

Traceway is a completely open-source error tracking platform. You can self-host it or use Traceway Cloud.

This is the React Native counterpart to @tracewayapp/react (web) and com.tracewayapp:traceway (native Android). The wire format is identical, so the same Traceway backend ingests reports from all three.

No screen recording. Unlike the browser SDK (@tracewayapp/frontend), this package does not record the screen. The rrweb recorder is intentionally absent — nothing in the bundle reaches into a DOM that doesn't exist.

Features

  • Automatic capture of every uncaught throw via React Native's ErrorUtils global handler
  • Automatic capture of unhandled promise rejections
  • Full Hermes / JavaScriptCore stack traces, normalized to Traceway's wire format
  • Logs — every console.{debug,log,info,warn,error} line from the last ~10 seconds
  • Actions — every fetch and XMLHttpRequest call, plus navigation transitions you wire in, plus custom breadcrumbs
  • React surface: <TracewayProvider>, <TracewayErrorBoundary>, useTraceway() hook
  • Debounced, retrying batch transport over plain fetch (no native modules, works in Expo Go)
  • Simple one-line setup

Installation

npm install @tracewayapp/react-native

The package is plain JavaScript — no native modules, no pod install, no Gradle changes. It works in Expo Go, in bare React Native CLI projects, and in EAS builds.

Quick Start

Wrap your app in TracewayProvider from your entry component (typically App.tsx). Mounting the provider runs init(...) once, which installs the ErrorUtils global handler, the fetch / XHR wrappers, and the console mirror.

import { TracewayProvider, TracewayErrorBoundary } from "@tracewayapp/react-native";

export default function App() {
  return (
    <TracewayProvider
      connectionString="your-token@https://your-traceway-instance.com/api/report"
      options={{ version: "1.0.0" }}
    >
      <TracewayErrorBoundary fallback={<CrashScreen />}>
        <RootNavigator />
      </TracewayErrorBoundary>
    </TracewayProvider>
  );
}

That's it. Every uncaught throw, unhandled promise rejection, and fetch call is captured automatically.

Manual Capture

import { useTraceway } from "@tracewayapp/react-native";
import { captureException, captureMessage, flush } from "@tracewayapp/react-native";

// Inside a component — get scoped helpers from the hook:
function CheckoutButton() {
  const { captureException, recordAction } = useTraceway();
  // ...
}

// Or import directly anywhere (after init has run):
try {
  riskyOperation();
} catch (e) {
  captureException(e as Error);
}

captureMessage("User completed checkout");

// Force send pending events (e.g. before app goes to background):
await flush();

Options

All field names mirror the browser and Android SDKs so existing config can be ported as-is.

| Option | Default | Description | |--------|---------|-------------| | version | "" | App version string, attached to every report | | debug | false | Print debug info to the console | | debounceMs | 1500 | Milliseconds before flushing batched events | | retryDelayMs | 10000 | Retry delay on failed uploads | | ignoreErrors | sensible defaults | Array of string \| RegExp patterns; matching exceptions are dropped | | beforeCapture | none | (exception) => boolean — return false to drop | | captureLogs | true | Mirror every console.* call into the rolling log buffer | | captureNetwork | true | Record fetch and XMLHttpRequest calls as network actions | | captureNavigation | true | Record manual recordNavigation() calls | | captureDeviceInfo | true | Auto-collect os.name, os.version, screen, locale, runtime engine and attach to every report | | eventsWindowMs | 10000 | Rolling window kept in the log/action buffers (ms) | | eventsMaxCount | 200 | Hard cap applied independently to logs and actions |

The DEFAULT_IGNORE_PATTERNS export contains the built-in ignoreErrors list (Network request failed, Failed to fetch, generic 4xx, etc.) — you can extend it rather than replace it.

Logs & Actions

Every captured exception ships with the last ~10 seconds of session context, attached to the same sessionRecordings[] entry the other Traceway SDKs use:

  • Logs — every console.{debug,log,info,warn,error} call. The original console output is preserved; we only piggyback on the call.
  • Actions are split into three channels:
    • Network — every fetch and XMLHttpRequest call (method, URL, status, duration, byte counts). Calls to the Traceway endpoint itself are skipped to avoid recursion.
    • Navigation — push transitions you record manually (see below).
    • Custom — anything you call recordAction(...) with.

Logs and actions are kept in two separate rolling buffers, each capped at 200 entries / 10 seconds. They ship inside sessionRecordings[].logs and sessionRecordings[].actions on the wire, with startedAt / endedAt ISO 8601 timestamps spanning the captured window.

Navigation capture

React Native has no window.history to auto-instrument. Wire recordNavigation into whatever navigation library you use:

import { useNavigationContainerRef } from "@react-navigation/native";
import { recordNavigation } from "@tracewayapp/react-native";

const navigationRef = useNavigationContainerRef();
const prevRoute = useRef<string | null>(null);

return (
  <NavigationContainer
    ref={navigationRef}
    onStateChange={() => {
      const next = navigationRef.getCurrentRoute()?.name ?? "unknown";
      recordNavigation(prevRoute.current ?? "(initial)", next);
      prevRoute.current = next;
    }}
  >
    {/* ... */}
  </NavigationContainer>
);

For Expo Router drop the same call into a useEffect keyed on usePathname().

Record a custom action

import { recordAction } from "@tracewayapp/react-native";

recordAction("cart", "add_item", { sku: "SKU-123", qty: 2 });

Disable a channel

Each channel can be turned off individually via TracewayProvider's options:

<TracewayProvider
  connectionString={DSN}
  options={{
    captureLogs: false,
    captureNetwork: false,
    captureNavigation: false,
  }}
>

Attributes

Every captured exception ships with an attributes map composed of three layers (per-call wins, then global scope, then device info):

1. Device info — auto-collected

Auto-stamped at init() from React Native core APIs (no native modules required, works in Expo Go). The keys mirror what the Flutter and Android SDKs emit so the dashboard renders them consistently across platforms:

| Key | Source | |---|---| | os.name | Platform.OS (ios / android / web) | | os.version | Platform.Version | | screen.resolution | Dimensions.get("screen") (whole pixels) | | screen.density | PixelRatio.get() | | device.locale | Intl.DateTimeFormat().resolvedOptions().locale | | runtime.engine | hermes / javascriptcore |

To replace or extend the auto-collected map at runtime (e.g. add info from expo-device / react-native-device-info you've installed yourself):

import { setDeviceAttributes, collectSyncDeviceInfo } from "@tracewayapp/react-native";
import * as Device from "expo-device";

setDeviceAttributes({
  ...collectSyncDeviceInfo(),  // keep the auto-collected ones
  "device.model": Device.modelName ?? "",
  "device.manufacturer": Device.manufacturer ?? "",
});

To opt out of device info collection entirely, pass captureDeviceInfo: false in options.

2. Global scope — app-level identifiers

Use the global scope for things tied to the user / tenant / app state, not the device: user id, organization id, build channel, feature flags, A/B bucket. Two ways to set it.

Declarative — <TracewayAttributes> or the useTracewayAttributes hook. Pass a map; the SDK diffs against the previous map and pushes only the deltas. On unmount, every key the component owned is removed.

import { TracewayAttributes, useTracewayAttributes } from "@tracewayapp/react-native";

// As a component — drop in wherever you have user/tenant context:
<TracewayAttributes attributes={user ? { userId: user.id, tenant: org.id } : null} />

// Or as a hook:
function App() {
  useTracewayAttributes({ build_channel: "canary" });
  return <RootNavigator />;
}

The hook accepts null / undefined as "empty map" — useful while user data loads or after logout.

Imperative — setAttribute / setAttributes / removeAttribute / clearAttributes. Use these outside React component trees (auth listeners, background tasks):

import {
  setAttribute,
  setAttributes,
  clearAttributes,
} from "@tracewayapp/react-native";

setAttribute("userId", "u_42");
setAttributes({ tenant: "acme", plan: "pro" });
// ...on logout:
clearAttributes();

3. Per-call attributes

captureExceptionWithAttributes(error, attrs) — wins on key collision over both layers above.

Layering

For each captured exception: device info < global scope < per-call. The same precedence applies to sessions when always-on session recording is on.

What Gets Captured Automatically

  • Uncaught throws on the JS thread via ErrorUtils.setGlobalHandler — this is RN's equivalent of window.onerror. RN's red-box dev overlay still appears; we forward to the previous handler.
  • Unhandled promise rejectionsPromise.reject(...) without a .catch() reaches the same ErrorUtils handler.
  • fetch calls — wrapped at install time. Method, URL, status, duration, byte counts.
  • XMLHttpRequest calls — RN polyfills XHR (and fetch is implemented on top of it on some platforms); both paths are covered.
  • Render errors — when wrapped in <TracewayErrorBoundary>, exceptions thrown during render or in lifecycle methods are captured.
  • Console outputconsole.{debug,log,info,warn,error} is mirrored into the log buffer that rides along the next exception.

Platform Support

| Platform | Error Tracking | Screen Recording | |----------|----------------|------------------| | iOS (RN ≥ 0.72) | Yes | No | | Android (RN ≥ 0.72) | Yes | No | | Expo (SDK 49+) | Yes — works in Expo Go | No | | Web (via React Native Web) | Yes | No |

For native Android-only apps without React Native, use the com.tracewayapp:traceway library. For browser apps, use @tracewayapp/frontend or @tracewayapp/react.

Running the example app

The examples/expo-demo directory is a tiny throwaway Expo app with buttons that exercise every capture path (caught throw, uncaught throw, render error, fetch error, custom action).

To point it at your own Traceway backend:

cd packages/react-native/examples/expo-demo
npm install
TRACEWAY_DSN="YOUR_TOKEN@https://your-traceway-instance.com/api/report" npx expo start

Then open it in Expo Go (scan the QR code), or press i / a for iOS simulator / Android emulator.

If TRACEWAY_DSN is missing, the app falls back to a placeholder DSN that won't reach any real server — the buttons still fire so you can verify the UI.

Running the tests

JVM-fast Vitest unit tests cover the wire-format, the rolling event buffer, ignore-pattern handling, transport, retry logic, and stack-trace formatting against fake Hermes / JavaScriptCore stacks.

npm test --workspace=@tracewayapp/react-native

Publishing

Releases are cut through the monorepo's publish.sh — it bumps every @tracewayapp/* package in lockstep, syncs cross-package dependency references, builds, and publishes. From the repo root:

./publish.sh

The script prompts for a new semver and confirms before pushing to npm. If publish fails, no commit or tag is created — fix the issue and re-run.

Links

License

MIT