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

noibu-react-native

v1.0.1

Published

Noibu session replay and error monitoring SDK for React Native

Downloads

6,064

Readme

noibu-react-native (v2)

Noibu session replay and error monitoring for React Native. v2 is a thin JS layer over the same native SDKs every Noibu mobile app uses: on Android the com.noibu.mobile.android:session-replay module (100% Noibu-owned rrweb capture — replay, touches with DXA selectors, keyboard, network, crashes), on iOS the NoibuSessionReplay Swift package.

See the CHANGELOG for the v0.x → v2 changes and breaking changes.

Install

npm install noibu-react-native
cd ios && pod install   # iOS

Supports both the old and the new React Native architecture — one legacy native module, which RN's interop layer bridges on bridgeless.

iOS Podfile

Autolinking picks the pod up; nothing needs adding to your target block. Three notes:

  • Your app must target iOS 14.0 or newer. React Native's template Podfile uses platform :ios, min_ios_version_supported, which is below 14.0 on every React Native this package supports (13.4 on 0.75), so a default app fails to resolve before it builds anything: Specs satisfying the NoibuSessionReplay dependency were found, but they required a higher minimum deployment target. Set platform :ios, '14.0' (or higher) in your Podfile and match it in your app target's IPHONEOS_DEPLOYMENT_TARGET.
  • Keep your existing linkage. The iOS SDK vendors a dynamic coreKit.xcframework, which CocoaPods embeds into your app under any linkage mode — including use_frameworks! :linkage => :static (the RN default) and no use_frameworks! at all. Do not switch to bare use_frameworks!: Hermes does not support dynamic frameworks.
  • Xcode 15+ blocks the embed. ENABLE_USER_SCRIPT_SANDBOXING defaults to YES, which makes CocoaPods' [CP] Embed Pods Frameworks phase fail with Sandbox: rsync ... Operation not permitted and the app then crashes at launch with Library not loaded: @rpath/coreKit.framework/coreKit. Set it to No on your app target, or in the Podfile:
post_install do |installer|
  installer.aggregate_targets.each do |aggregate_target|
    aggregate_target.user_project.native_targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
      end
    end
    aggregate_target.user_project.save
  end
end

Android Gradle

Autolinking picks the module up; it resolves com.noibu.mobile.android:session-replay from Maven Central, which every React Native template already lists. One requirement:

  • minSdkVersion must be at least 26 (Android 8.0). React Native itself builds at 23, and the app template inherits that, so a default app fails the build before it compiles anything:

    Manifest merger failed : uses-sdk:minSdkVersion 23 cannot be smaller than version 26
    declared in library [com.noibu.mobile.android:session-replay]

    Raise minSdkVersion in android/build.gradle. v0.x had no floor of its own — it inherited the app's — so this is an upgrade step for existing integrations.

Initialize

import { Noibu } from 'noibu-react-native';

Noibu.init({
  domain: 'shop.example.com', // provided by Noibu
});

Call it early (e.g. top of index.js / App.tsx). All capture starts natively — no further wiring required. Optional config:

Noibu.init({
  domain: 'shop.example.com',
  logLevel: 'info',            // integration-debugging diagnostics
  trackTouches: true,
  trackKeyboard: true,
  trackNetwork: true,          // kill switch for all HTTP capture
  trackErrors: true,           // JS handlers + native crash handler
  autoTrackNavigation: false,  // native page per Activity/Fragment (no-wiring fallback)
});

Lifecycle

Noibu.isInitialized is true between a successful init and shutdown. shutdown() stops all capture, flushes the native pipeline and re-opens init, so the SDK can be cycled inside one process (a logout, an app that only records part of its flows):

await Noibu.shutdown();
// … later, a new session starts from scratch
await Noibu.init({ domain: 'shop.example.com' });

It resolves once the native teardown has run and never rejects. Errors and attributes reported while the SDK is down return NOT_INITIALIZED and — exactly as before the first init — are buffered (bounded) and applied to the next session if one starts. What the ended session had buffered is dropped rather than replayed into it.

Pages (react-navigation)

import { createNavigationContainerRef, NavigationContainer } from '@react-navigation/native';
import { useNoibuNavigation } from 'noibu-react-native';

const navigationRef = createNavigationContainerRef();

function App() {
  useNoibuNavigation(navigationRef);
  return <NavigationContainer ref={navigationRef}>…</NavigationContainer>;
}

Other routers: call Noibu.trackNavigation('ScreenName') when a screen appears, or set autoTrackNavigation: true.

Errors & attributes

Noibu.addError(new Error('Payment declined'));
Noibu.addError('Payment declined', stackString);
Noibu.addCustomAttribute('customerId', '42');

You don't have to await Noibu.init first: attributes set while it is still in flight are held (up to the 10-attribute limit) and applied when it lands, and the same is true of errors and page names. They still return the v0.x NOT_INITIALIZED string in that window.

Up to 500 errors are reported per page visit (the SDK caps them natively, so the count resets on every page visit — including the ones it opens itself when the app returns from the background).

Uncaught JS exceptions, unhandled promise rejections (Hermes) and native crashes are captured automatically. Wrap subtrees with ErrorBoundary to also catch React render errors:

import { ErrorBoundary } from 'noibu-react-native';
<ErrorBoundary fallback={<Oops />}>…</ErrorBoundary>

The v0.x setupNoibu and NoibuJS.* entry points still work (deprecated — see the CHANGELOG).

Network capture

Both platforms capture JS fetch/XHR, remote <Image> loads and native requests with no JS patching, on bare React Native and on Expo alike. Nothing to wire up: autolinking and pod install are the whole integration.

Capture is installed as the app starts rather than when Noibu.init resolves, because the HTTP clients an app sends through are built during startup — an Expo app's fetch and every remote image went uncaptured while this waited for init. Requests are still only recorded while the SDK is initialized and trackNetwork is on, so the early install changes nothing else. WebSocket connections are not reported as requests: they carry no response, and a reconnecting socket would otherwise arrive as a run of failed requests.

If your app installs its own factory/provider, add Noibu to it instead (installNetworkInstrumentation() is idempotent, so doing both is safe):

OkHttpClientProvider.setOkHttpClientFactory {
  OkHttpClientProvider.createClientBuilder(context)
    .installNetworkInstrumentation() // com.noibu.mobile.sessionreplay.api
    .build()
}

Request/response bodies and header values are captured (up to 64 KB) and PII-redacted before they touch the device cache: values under sensitive key names (password, email, cardNumber, …) are replaced, then card / email / SSN / SIN / phone patterns are scrubbed from the remaining text — the same rule the v0.x JS SDK applied.

GraphQL responses are checked for failures the status code hides: a 2xx JSON response at a graphql URL (or application/graphql) carrying an errors array is reported as an error per entry, so a declined payment isn't filed as a successful call.

RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
  NSURLSessionConfiguration *configuration = NSURLSessionConfiguration.defaultSessionConfiguration;
  [[NoibuHTTPInterceptor shared] installNetworkInstrumentationOn:configuration]; // @import NoibuSessionReplay
  return configuration;
});

WebView capture (hybrid replay)

Wrap web content in NoibuWebView — a drop-in replacement for react-native-webview's WebView that enables Noibu tracking on the underlying native webview BEFORE its first document loads (replay, clicks, JS errors and HTTP of the page join the session timeline):

import { NoibuWebView } from 'noibu-react-native';

<NoibuWebView source={{ uri: 'https://shop.example.com/checkout' }} />

It takes the same props as WebView (including ref) and fills its parent by default; pass style to size it explicitly. Mount order doesn't matter — a webview on the opening screen waits for Noibu.init to land before loading its content, and renders untracked as soon as init fails (or after a short wait, if init is never called at all).

Input values inside a tracked webview are masked in replay (rrweb's own default masks passwords only), and a click on a field reports the field's label, not its content — the same rule the native walkers apply to <TextInput>.

Requires the optional peer dependency react-native-webview >= 13. Webviews rendered with the plain WebView component are NOT captured — wrapping is the per-webview opt-in (mirror of the native SDK's WebViewTracking.enable), so sensitive webviews (payment 3DS, SSO) stay untracked by simply not wrapping them. trackWebViews: false in NoibuConfig disables webview capture SDK-wide regardless of wrapping.

Known limitations

  • privacyMode is not selectable — both native SDKs now mask display text behind it, but the bridge does not pass the flag, so an RN app always gets the native default MASK_SENSITIVE: card/SSN/email/phone spans in rendered text are scrubbed, everything else replays as written. <TextInput> content is never captured on any mode — both platforms' walkers ship the field's placeholder (or *** when it has none) instead of what the user typed, and the keyboard monitor records the focused field, not its contents. Inputs inside a NoibuWebView are masked too.
  • Android animated images: a GIF or animated WebP replays as its first frame (React Native reuses one drawable object for the whole animation). Static images are captured when they load and again whenever their source changes.
  • <ActivityIndicator>: a spinner replays as a still image of its first frame — its presence is what the session records, not its rotation.
  • Animated SVGs: a continuously animating react-native-svg graphic replays its first 30 redraws and then freezes — each distinct render is its own replay asset. <Svg> content that changes with state (an icon recolouring, a filled/outline toggle) is captured on every change. The same 30-change bound covers the other rasterized controls (<Switch>, a determinate progress bar, a slider), so a slider dragged across many values freezes once it is reached.
  • iOS truncated text: a numberOfLines={1} title that ends in an ellipsis on device replays in full and can overrun the elements beside it — UIKit exposes no truncation state, so deciding it would mean measuring every text view on every capture. Android clips it back to its box.
  • iOS borders under the new architecture: React Native draws its own borders on iOS and keeps the widths/colours in C++ under Fabric, where the capture cannot read them — so a bordered view (outlined card, list separator, input underline) replays with no border on a Fabric host. Apps on the old architecture, and Android, capture them.
  • RN < 0.72: corner radii of RN-drawn native views may not be captured in replay (backgrounds and borders are; older hosts degrade gracefully — text, layout and images still capture).