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

network-smart-handler

v1.0.3

Published

A smart network handler package for Web and React Native that provides intelligent network detection, automatic request queuing, retry logic, and user-friendly notifications.

Downloads

438

Readme

Network Smart Handler

A smart network handler package for React and React Native applications. Provides intelligent network status detection (Weak/Medium/Strong), customizable retry logic, automatic request queuing, and ready-to-use notifications.

Features

  • Simple API - getNetworkState() gives you state directly without Provider
  • Intelligent Network Detection - Not just online/offline, but Weak/Medium/Strong quality levels
  • Retry Logic - Multiple strategies (fixed, exponential, exponential-jitter)
  • Automatic Request Queuing - Saves requests when offline and retries automatically
  • Ready-to-use Notifications - Customizable Banner/Toast components
  • Easy Hooks - useNetworkStatus(), useSmartFetch(), useQueuedRequests()
  • Cross-platform - Works on Web and React Native (Android/iOS)
  • Observability - Statistics and telemetry callbacks
  • Adapters - Support for fetch and axios

Installation

npm install network-smart-handler
# or
yarn add network-smart-handler

React Native

For React Native, you also need to install @react-native-community/netinfo:

npm install @react-native-community/netinfo
# or
yarn add @react-native-community/netinfo

Quick Start

Simple API (No Provider Required)

The easiest way to use the library! Just call the function and get state directly:

import { getNetworkState, initNetworkHandler, simpleSmartFetch } from 'network-smart-handler';

// Initialize (optional - can use defaults)
initNetworkHandler({
  retry: {
    maxAttempts: 3,
    strategy: 'exponential',
  },
});

// Get state directly - anywhere in your code
const state = getNetworkState();
console.log(state.isOnline);    // true/false
console.log(state.quality);     // 'weak' | 'medium' | 'strong'
console.log(state.type);        // 'wifi' | 'cellular' | 'ethernet' | 'unknown'
console.log(state.latency);     // number in milliseconds
console.log(state.statistics);   // network statistics
console.log(state.queuedRequests); // queued requests

// Use smart fetch
const response = await simpleSmartFetch('https://api.example.com/data');
const data = await response.json();

React Component Example

import { useEffect, useState } from 'react';
import { getNetworkState, subscribeToNetworkState } from 'network-smart-handler';

function MyComponent() {
  const [networkState, setNetworkState] = useState(getNetworkState());

  useEffect(() => {
    const unsubscribe = subscribeToNetworkState((state) => {
      setNetworkState(state);
    });
    return unsubscribe;
  }, []);

  return (
    <div>
      <p>Network: {networkState.isOnline ? 'Online' : 'Offline'}</p>
      <p>Quality: {networkState.quality}</p>
      <p>Type: {networkState.type}</p>
    </div>
  );
}

Advanced Usage

Provider Setup

import { NetworkProvider } from 'network-smart-handler';
import { App } from './App';

export default function Root() {
  return (
    <NetworkProvider
      config={{
        retry: {
          maxAttempts: 3,
          strategy: 'exponential',
          baseDelay: 1000,
        },
        queue: {
          policy: 'drop-oldest',
          maxSize: 100,
          persistToStorage: true,
        },
        enableQualityTesting: true,
        qualityThresholds: {
          weak: 1000,   // latency > 1000ms = weak
          medium: 300, // latency > 300ms = medium
        },
      }}
      showNotification={true}
    >
      <App />
    </NetworkProvider>
  );
}

Using Hooks

import { useNetworkStatus, useSmartFetch } from 'network-smart-handler';

function MyComponent() {
  const { isOnline, quality, status } = useNetworkStatus();
  const { smartFetch } = useSmartFetch();

  const handleFetch = async () => {
    try {
      const response = await smartFetch('https://api.example.com/data', {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
      }, {
        maxAttempts: 5, // Override per-request
        strategy: 'exponential-jitter',
      });
      
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Request failed:', error);
    }
  };

  return (
    <div>
      <p>Network: {isOnline ? 'Online' : 'Offline'}</p>
      <p>Quality: {quality}</p>
      <p>Latency: {status.latency}ms</p>
      <button onClick={handleFetch}>Fetch Data</button>
    </div>
  );
}

Custom Notification

import { NetworkNotification, useNetworkStatus, useQueuedRequests } from 'network-smart-handler';

function CustomNotification() {
  const { status } = useNetworkStatus();
  const queuedRequests = useQueuedRequests();

  return (
    <NetworkNotification
      status={status}
      queuedCount={queuedRequests.length}
      variant="toast"
      position="bottom"
      style={{
        backgroundColor: '#333',
        textColor: '#fff',
        borderRadius: 12,
      }}
      onRetry={() => {
        // Manual retry logic
      }}
      onDismiss={() => {
        // Handle dismiss
      }}
    />
  );
}

API Reference

NetworkProvider

<NetworkProvider
  config?: NetworkHandlerConfig
  storage?: StorageAdapter
  showNotification?: boolean
>
  {children}
</NetworkProvider>

NetworkHandlerConfig

interface NetworkHandlerConfig {
  retry?: {
    maxAttempts?: number;        // Default: 3
    strategy?: 'fixed' | 'exponential' | 'exponential-jitter' | 'exponential-partial-jitter';
    baseDelay?: number;           // Default: 1000ms
    maxDelay?: number;            // Default: 30000ms
    retryableStatuses?: number[]; // HTTP status codes to retry
    retryableErrors?: string[];   // Error types to retry
  };
  queue?: {
    policy?: 'drop-oldest' | 'drop-newest' | 'persist' | 'reject';
    maxSize?: number;
    persistToStorage?: boolean;
    storageKey?: string;
    priority?: boolean;
  };
  qualityThresholds?: {
    weak: number;    // latency threshold in ms
    medium: number;  // latency threshold in ms
  };
  testEndpoint?: string;
  enableQualityTesting?: boolean;
  qualityTestInterval?: number;
  respectDataSaver?: boolean;
}

Hooks

useNetworkStatus()

const {
  status: NetworkStatus,      // Current network status
  statistics: NetworkStatistics, // Network statistics
  queuedRequests: QueuedRequest[], // Queued requests
  isOnline: boolean,
  quality: 'weak' | 'medium' | 'strong',
  smartFetch: (url, options?, retryConfig?) => Promise<Response>,
  clearQueue: () => Promise<void>,
  onTelemetry: (callback) => () => void,
} = useNetworkStatus();

useSmartFetch()

const { smartFetch } = useSmartFetch();

const response = await smartFetch(
  'https://api.example.com/data',
  { method: 'GET' },
  { maxAttempts: 5 } // Optional retry config
);

useQueuedRequests()

const queuedRequests = useQueuedRequests();

useNetworkStatistics()

const statistics = useNetworkStatistics();
// {
//   queuedRequests: number,
//   retrySuccessRate: number,
//   averageLatency: number,
//   lastNetworkReturn?: number,
//   totalRequests: number,
//   successfulRequests: number,
//   failedRequests: number,
//   retryAttempts: number,
// }

Adapters

Fetch Adapter

import { NetworkHandler, replaceGlobalFetch } from 'network-smart-handler';

const handler = new NetworkHandler(config);
const restore = replaceGlobalFetch(handler);

// Now all fetch() calls use smart fetch
fetch('https://api.example.com/data');

// Restore original fetch
restore();

Axios Adapter

import axios from 'axios';
import { NetworkHandler, applyAxiosInterceptor, withRetryConfig } from 'network-smart-handler';

const handler = new NetworkHandler(config);
const cleanup = applyAxiosInterceptor(axios, handler);

// Use with retry config
axios.get('https://api.example.com/data', withRetryConfig({}, {
  maxAttempts: 5,
  strategy: 'exponential-jitter',
}));

// Cleanup
cleanup();

HOC

import { withNetworkHandler } from 'network-smart-handler';

const MyComponent = ({ status, smartFetch, isOnline }) => {
  // Component logic
};

export default withNetworkHandler(MyComponent);

Retry Strategies

  1. fixed: Fixed delay between retries
  2. exponential: Exponential backoff (2^n * baseDelay)
  3. exponential-jitter: Exponential with full jitter (random 0 to calculated delay)
  4. exponential-partial-jitter: Exponential with partial jitter (random between delay/2 and delay)

Queue Policies

  1. drop-oldest: Remove oldest request when queue is full
  2. drop-newest: Reject new requests when queue is full
  3. persist: Persist queue to storage (AsyncStorage/IndexedDB)
  4. reject: Throw error when queue is full

Telemetry

const { onTelemetry } = useNetworkStatus();

useEffect(() => {
  const unsubscribe = onTelemetry((event) => {
    console.log('Network event:', event.type, event.data);
    // Send to analytics, logging service, etc.
  });

  return unsubscribe;
}, []);

Storage Adapters

Web (LocalStorage/IndexedDB)

import { WebStorageAdapter } from 'network-smart-handler';

const storage = new WebStorageAdapter(useIndexedDB: boolean);

React Native (AsyncStorage)

import AsyncStorage from '@react-native-async-storage/async-storage';
import { RNStorageAdapter } from 'network-smart-handler';

const storage = new RNStorageAdapter(AsyncStorage);

Examples

Example 1: Basic Usage with Notification

import { NetworkProvider, useSmartFetch } from 'network-smart-handler';

function App() {
  return (
    <NetworkProvider showNotification={true}>
      <DataFetcher />
    </NetworkProvider>
  );
}

function DataFetcher() {
  const { smartFetch } = useSmartFetch();
  const [data, setData] = useState(null);

  useEffect(() => {
    smartFetch('https://api.example.com/data')
      .then(res => res.json())
      .then(setData);
  }, []);

  return <div>{data && JSON.stringify(data)}</div>;
}

Example 2: Custom Retry Configuration

const { smartFetch } = useSmartFetch();

const response = await smartFetch(
  'https://api.example.com/data',
  { method: 'POST', body: JSON.stringify({ data: 'test' }) },
  {
    maxAttempts: 5,
    strategy: 'exponential-jitter',
    baseDelay: 2000,
    maxDelay: 60000,
    retryableStatuses: [500, 502, 503, 504, 429],
  }
);

Example 3: Priority Queue

<NetworkProvider
  config={{
    queue: {
      policy: 'drop-oldest',
      priority: true, // Enable priority queue
      maxSize: 50,
    },
  }}
>
  <App />
</NetworkProvider>

// Later in your code
const { smartFetch } = useSmartFetch();

// High priority request
await smartFetch('https://api.example.com/important', {
  method: 'POST',
  body: JSON.stringify({ priority: 10 }), // Higher number = higher priority
});

License

MIT

Contributing

Contributions are welcome! Please read our contributing guidelines.