JSPM

react-native-reliability

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q27444F
  • License MIT

A production-ready toolkit for React Native stability and observability

Package Exports

  • react-native-reliability
  • react-native-reliability/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-native-reliability) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

react-native-reliability

A lightweight, production-ready toolkit that improves stability and observability in React Native apps.


Why?

React Native apps fail silently in production for many common reasons:

Problem This toolkit
Unhandled async errors safeAsync — wraps promises with timeout & error capture
Component render crashes ReliabilityErrorBoundary — safe fallback UI + structured logging
Unstable network conditions useNetworkHealth — detects offline / slow / unstable states
Silent promise rejections safeAsync — global error callback
Background/foreground issues useAppLifecycle — lifecycle state tracking
Crash loops useCrashRecovery — detects repeated crashes on startup

Works with React Native CLI and Expo. Every module is fully independent — adopt only what you need.


Installation

# npm
npm install react-native-reliability

# yarn
yarn add react-native-reliability

Optional peer dependencies

Install these only for the modules you use:

# useNetworkHealth
npm install @react-native-community/netinfo

# useCrashRecovery (persistent storage across restarts)
npm install @react-native-async-storage/async-storage

Quick Start

import { ReliabilityProvider } from 'react-native-reliability';

export default function App() {
  return (
    <ReliabilityProvider>
      <MyApp />
    </ReliabilityProvider>
  );
}

Individual hooks and components work without the provider using sensible defaults.


Modules

1 — Error Boundary

Catches React render-tree crashes and renders a fallback UI.

import { ReliabilityErrorBoundary } from 'react-native-reliability';

<ReliabilityErrorBoundary
  fallback={<Text>Something went wrong. Please restart the app.</Text>}
  onError={(error, info) => {
    // send to crash analytics, record crash, etc.
    logError(error, info.componentStack);
  }}
>
  <App />
</ReliabilityErrorBoundary>

Props

Prop Type Description
fallback React.ReactNode UI shown when the tree crashes. Renders null if omitted.
onError (error: Error, info: React.ErrorInfo) => void Called when a render error is caught.
children React.ReactNode The component tree to protect.

2 — Network Health Monitor

Detects degraded connectivity without constant polling.

import { useNetworkHealth } from 'react-native-reliability';

const network = useNetworkHealth();

switch (network.status) {
  case 'offline':   /* show offline banner */ break;
  case 'slow':      /* show slow-network warning */ break;
  case 'unstable':  /* retry with backoff */ break;
  case 'healthy':   /* proceed normally */ break;
}

Requires @react-native-community/netinfo. Returns healthy (no-op) without it.

Returned object

Field Type Description
status 'healthy' | 'slow' | 'unstable' | 'offline' Overall network status
isOffline boolean No internet connection
isSlow boolean High latency detected
isUnstable boolean Frequent disconnect/reconnect

3 — Safe Async Wrapper

Prevents unhandled promise rejections and adds timeout protection.

import { safeAsync } from 'react-native-reliability';

safeAsync(
  () => fetchUser(userId),
  {
    timeout: 5000,
    onError: (error) => logError(error),
  }
)
  .then(handleUser)
  .catch(handleFetchError);

Options

Option Type Default Description
timeout number 10000 Milliseconds before a TimeoutError is thrown
onError (error: Error) => void Called for any error (including timeout)

4 — App Lifecycle Monitor

Tracks application foreground / background / inactive state transitions.

import { useAppLifecycle } from 'react-native-reliability';

const lifecycle = useAppLifecycle();

useEffect(() => {
  if (lifecycle.state === 'background') {
    stopNetworkPolling();
    saveUserSession();
  }
  if (lifecycle.state === 'active') {
    resumeNetworkPolling();
  }
}, [lifecycle.state]);

Returned object

Field Type Description
state 'active' | 'background' | 'inactive' Current lifecycle state

5 — Crash Recovery Helper

Detects repeated crash loops on startup and lets you recover gracefully.

import { useCrashRecovery, ReliabilityErrorBoundary } from 'react-native-reliability';

function Root() {
  const crash = useCrashRecovery();

  if (crash.hasRecentCrash) {
    return (
      <SafeModeScreen
        crashCount={crash.crashCount}
        onReset={crash.clearCrashHistory}
      />
    );
  }

  return (
    <ReliabilityErrorBoundary onError={crash.recordCrash}>
      <App />
    </ReliabilityErrorBoundary>
  );
}

Requires @react-native-async-storage/async-storage for persistence across restarts.
Falls back to in-memory storage (resets on every restart) when not installed.

Returned object

Field Type Description
hasRecentCrash boolean true when crashes ≥ crashThreshold within crashWindow
crashCount number Number of crashes in the current window
recordCrash (error?: Error) => Promise<void> Record a crash event
clearCrashHistory () => Promise<void> Clear all stored crash data

Provider Configuration

Override defaults globally with ReliabilityProvider:

<ReliabilityProvider
  config={{
    crashWindow: 120_000,          // 2 minute window (default: 60_000)
    crashThreshold: 3,             // crashes to trigger hasRecentCrash (default: 2)
    networkCheckUrl: 'https://api.myapp.com/health',
    slowNetworkThreshold: 3000,    // ms (default: 2000)
    unstableNetworkThreshold: 5,   // disconnects/min (default: 3)
  }}
>
  <App />
</ReliabilityProvider>

All hooks also accept these values from context automatically when wrapped in the provider.


Full Production Example

import React from 'react';
import {
  ReliabilityProvider,
  ReliabilityErrorBoundary,
  useNetworkHealth,
  useAppLifecycle,
  useCrashRecovery,
  safeAsync,
} from 'react-native-reliability';

function AppShell() {
  const network = useNetworkHealth();
  const lifecycle = useAppLifecycle();
  const crash = useCrashRecovery();

  // Show safe mode if crash loop detected
  if (crash.hasRecentCrash) {
    return <SafeModeScreen onReset={crash.clearCrashHistory} />;
  }

  return (
    <ReliabilityErrorBoundary
      onError={crash.recordCrash}
      fallback={<ErrorScreen />}
    >
      {network.isOffline && <OfflineBanner />}
      {lifecycle.state === 'active' && <MainApp />}
    </ReliabilityErrorBoundary>
  );
}

export default function App() {
  return (
    <ReliabilityProvider config={{ crashThreshold: 3 }}>
      <AppShell />
    </ReliabilityProvider>
  );
}

Design Philosophy

Stability, safety, and predictability — not analytics dashboards.

  • Never crashes the host app — all handlers are wrapped in try/catch
  • Minimal dependencies — peer deps are optional; modules work independently
  • No polling — event-driven where possible; ping on demand
  • Strict TypeScript — no any, full type coverage
  • Works in dev and production — same API, no build flags

Architecture

src/
  core/
    reliabilityProvider.tsx     ← shared config context (optional)
  modules/
    errorBoundary/
      ReliabilityErrorBoundary.tsx
    networkHealth/
      useNetworkHealth.ts
    safeAsync/
      safeAsync.ts
    lifecycle/
      useAppLifecycle.ts
    crashRecovery/
      useCrashRecovery.ts
  hooks/
    useNetworkHealth.ts         ← re-exports
    useAppLifecycle.ts
  types/
    reliabilityTypes.ts
  index.ts

License

MIT