logo-text
NetworkingCommunity LibraryReact Native

Master React Native NetInfo: The Ultimate Developer's Guide to Network Connectivity Magic ✨

By Viewlytics Team15 min readMay 31, 2025

React Native Community NetInfo is the most reliable library for monitoring network connectivity in React Native applications. This comprehensive guide covers everything from basic setup to advanced implementation patterns, helping you build robust offline-capable apps.

1. Understanding React Native NetInfo

NetInfo is a React Native library that provides information about the device's network connection status and type. Originally part of React Native core, it was moved to the community to enable faster updates and better platform support.

Key Features:
  • Real-time network status monitoring
  • Connection type detection (WiFi, Cellular, etc.)
  • Internet reachability testing
  • Cross-platform support (iOS, Android, Web, macOS, Windows)
  • TypeScript support
  • Configurable reachability testing

Installation and Setup

Install the library using npm or yarn:

# Using npm
npm install --save @react-native-community/netinfo

# Using yarn
yarn add @react-native-community/netinfo

For React Native 0.60+, the library auto-links. For iOS, run pod install:

# iOS only
cd ios && npx pod-install

2. Basic Usage Patterns

Using the useNetInfo Hook

The simplest way to access network information is through the useNetInfo hook:

import { useNetInfo } from '@react-native-community/netinfo';
import { View, Text } from 'react-native';

function NetworkStatus() {
  const netInfo = useNetInfo();

  return (
    <View>
      <Text>Type: {netInfo.type}</Text>
      <Text>Is Connected: {netInfo.isConnected?.toString()}</Text>
      <Text>Is Internet Reachable: {netInfo.isInternetReachable?.toString()}</Text>
      {netInfo.type === 'wifi' && (
        <Text>WiFi SSID: {netInfo.details?.ssid || 'Unknown'}</Text>
      )}
      {netInfo.type === 'cellular' && (
        <Text>Carrier: {netInfo.details?.carrier || 'Unknown'}</Text>
      )}
    </View>
  );
}

Event-Based Monitoring

For more control, use the addEventListener method:

import { useEffect, useState } from 'react';
import NetInfo from '@react-native-community/netinfo';

function useNetworkMonitor() {
  const [networkState, setNetworkState] = useState(null);

  useEffect(() => {
    // Subscribe to network state updates
    const unsubscribe = NetInfo.addEventListener(state => {
      console.log('Connection type:', state.type);
      console.log('Is connected:', state.isConnected);
      setNetworkState(state);
    });

    // Get initial state
    NetInfo.fetch().then(state => {
      setNetworkState(state);
    });

    // Cleanup subscription
    return () => unsubscribe();
  }, []);

  return networkState;
}

One-time Network Check

For checking network status on-demand:

import NetInfo from '@react-native-community/netinfo';

// Check current network state
async function checkNetworkStatus() {
  const state = await NetInfo.fetch();
  
  if (state.isConnected) {
    console.log('Device is online');
    
    if (state.isInternetReachable) {
      console.log('Internet is reachable');
    } else {
      console.log('Connected to network but no internet');
    }
  } else {
    console.log('Device is offline');
  }
  
  return state;
}

// Check specific network interface
async function checkWiFiStatus() {
  const wifiState = await NetInfo.fetch('wifi');
  console.log('WiFi SSID:', wifiState.details?.ssid);
  console.log('WiFi strength:', wifiState.details?.strength);
}

3. Advanced Configuration

Custom Reachability Configuration

Configure custom reachability testing for better reliability:

import NetInfo from '@react-native-community/netinfo';

// Configure NetInfo with custom settings
NetInfo.configure({
  reachabilityUrl: 'https://clients3.google.com/generate_204',
  reachabilityTest: async (response) => response.status === 204,
  reachabilityLongTimeout: 60 * 1000, // 60s
  reachabilityShortTimeout: 5 * 1000, // 5s
  reachabilityRequestTimeout: 15 * 1000, // 15s
  reachabilityShouldRun: () => true,
  shouldFetchWiFiSSID: true, // iOS only - requires proper permissions
  useNativeReachability: false
});

Isolated Instance Usage

Use isolated instances for different configurations:

import { useNetInfoInstance } from '@react-native-community/netinfo';

function IsolatedNetworkMonitor() {
  const config = {
    reachabilityUrl: 'https://api.myapp.com/health',
    reachabilityTest: async (response) => {
      const data = await response.json();
      return data.status === 'ok';
    },
    reachabilityShortTimeout: 3000,
  };

  const { netInfo, refresh } = useNetInfoInstance(false, config);

  const handleRefresh = () => {
    refresh().then(state => {
      console.log('Refreshed network state:', state);
    });
  };

  return (
    <View>
      <Text>Connection: {netInfo.type}</Text>
      <Button title="Refresh" onPress={handleRefresh} />
    </View>
  );
}

4. Real-World Implementation Patterns

Offline-First Architecture

Build a robust offline-first app architecture:

import { useNetInfo } from '@react-native-community/netinfo';
import AsyncStorage from '@react-native-async-storage/async-storage';

function useOfflineCapability() {
  const netInfo = useNetInfo();
  const [offlineActions, setOfflineActions] = useState([]);

  // Queue actions when offline
  const queueOfflineAction = async (action) => {
    if (!netInfo.isInternetReachable) {
      const stored = await AsyncStorage.getItem('offlineActions');
      const actions = stored ? JSON.parse(stored) : [];
      actions.push({ ...action, timestamp: Date.now() });
      await AsyncStorage.setItem('offlineActions', JSON.stringify(actions));
      setOfflineActions(actions);
    }
  };

  // Process queued actions when back online
  useEffect(() => {
    if (netInfo.isInternetReachable && offlineActions.length > 0) {
      processOfflineActions();
    }
  }, [netInfo.isInternetReachable]);

  const processOfflineActions = async () => {
    const stored = await AsyncStorage.getItem('offlineActions');
    if (!stored) return;

    const actions = JSON.parse(stored);
    
    for (const action of actions) {
      try {
        await executeAction(action);
      } catch (error) {
        console.error('Failed to execute offline action:', error);
      }
    }

    await AsyncStorage.removeItem('offlineActions');
    setOfflineActions([]);
  };

  return { queueOfflineAction, isOnline: netInfo.isInternetReachable };
}

Smart Data Synchronization

Implement intelligent sync based on connection type:

import { useNetInfo } from '@react-native-community/netinfo';

function useSmartSync() {
  const netInfo = useNetInfo();

  const syncData = async (priority = 'normal') => {
    if (!netInfo.isInternetReachable) {
      console.log('No internet connection, skipping sync');
      return;
    }

    // Adjust sync behavior based on connection type
    let syncConfig = {
      batchSize: 100,
      enableImages: true,
      enableVideos: true,
      timeout: 30000,
    };

    if (netInfo.type === 'cellular') {
      if (netInfo.details?.isConnectionExpensive) {
        // Reduce data usage on expensive connections
        syncConfig = {
          batchSize: 20,
          enableImages: false,
          enableVideos: false,
          timeout: 15000,
        };
      }
    }

    if (netInfo.type === 'wifi') {
      // Full sync on WiFi
      syncConfig.batchSize = 500;
    }

    // Prioritize critical data
    if (priority === 'high') {
      return await syncCriticalData(syncConfig);
    }

    return await syncAllData(syncConfig);
  };

  return { syncData, connectionType: netInfo.type };
}

Connection Quality Monitoring

Monitor and adapt to connection quality:

import { useNetInfo } from '@react-native-community/netinfo';

function useConnectionQuality() {
  const netInfo = useNetInfo();
  const [quality, setQuality] = useState('unknown');

  useEffect(() => {
    if (!netInfo.isConnected) {
      setQuality('offline');
      return;
    }

    if (netInfo.type === 'wifi') {
      const strength = netInfo.details?.strength;
      if (strength && strength > 75) {
        setQuality('excellent');
      } else if (strength && strength > 50) {
        setQuality('good');
      } else {
        setQuality('poor');
      }
    } else if (netInfo.type === 'cellular') {
      const generation = netInfo.details?.cellularGeneration;
      switch (generation) {
        case '5g':
          setQuality('excellent');
          break;
        case '4g':
          setQuality('good');
          break;
        case '3g':
          setQuality('fair');
          break;
        case '2g':
          setQuality('poor');
          break;
        default:
          setQuality('unknown');
      }
    }
  }, [netInfo]);

  const getImageQuality = () => {
    switch (quality) {
      case 'excellent':
        return 'high';
      case 'good':
        return 'medium';
      case 'fair':
      case 'poor':
        return 'low';
      default:
        return 'low';
    }
  };

  return { quality, getImageQuality };
}

5. Best Practices and Performance Tips

Optimize Listener Management

Properly manage event listeners to avoid memory leaks:

import { useEffect, useRef } from 'react';
import NetInfo from '@react-native-community/netinfo';

function useNetworkListener(callback) {
  const callbackRef = useRef(callback);
  callbackRef.current = callback;

  useEffect(() => {
    let unsubscribe;

    const setupListener = async () => {
      // Get initial state
      const initialState = await NetInfo.fetch();
      callbackRef.current(initialState);

      // Subscribe to changes
      unsubscribe = NetInfo.addEventListener(state => {
        callbackRef.current(state);
      });
    };

    setupListener();

    return () => {
      if (unsubscribe) {
        unsubscribe();
      }
    };
  }, []);
}

Debounce Network State Changes

Prevent excessive API calls during network fluctuations:

import { useState, useEffect, useRef } from 'react';
import { useNetInfo } from '@react-native-community/netinfo';

function useDebouncedNetInfo(delay = 1000) {
  const netInfo = useNetInfo();
  const [debouncedNetInfo, setDebouncedNetInfo] = useState(netInfo);
  const timeoutRef = useRef();

  useEffect(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }

    timeoutRef.current = setTimeout(() => {
      setDebouncedNetInfo(netInfo);
    }, delay);

    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, [netInfo, delay]);

  return debouncedNetInfo;
}

Handle iOS Background Limitations

Account for iOS limitations when switching WiFi networks:

import { useEffect } from 'react';
import { AppState, Platform } from 'react-native';
import NetInfo from '@react-native-community/netinfo';

function useIOSNetworkRefresh() {
  useEffect(() => {
    if (Platform.OS !== 'ios') return;

    const handleAppStateChange = async (nextAppState) => {
      if (nextAppState === 'active') {
        // Refresh network state when app becomes active
        const newState = await NetInfo.refresh();
        console.log('Refreshed network state on iOS:', newState);
      }
    };

    const subscription = AppState.addEventListener('change', handleAppStateChange);

    return () => subscription?.remove();
  }, []);
}

6. Testing Strategies

Mocking NetInfo for Tests

Set up proper mocking for unit tests:

// jest.setup.js
import mockRNCNetInfo from '@react-native-community/netinfo/jest/netinfo-mock.js';

jest.mock('@react-native-community/netinfo', () => mockRNCNetInfo);

// Custom mock for specific test scenarios
export const createNetInfoMock = (initialState) => ({
  addEventListener: jest.fn(() => jest.fn()),
  fetch: jest.fn(() => Promise.resolve(initialState)),
  refresh: jest.fn(() => Promise.resolve(initialState)),
  configure: jest.fn(),
  useNetInfo: jest.fn(() => initialState),
});

Integration Testing

Test network-dependent features:

// NetworkComponent.test.js
import { render, waitFor } from '@testing-library/react-native';
import NetInfo from '@react-native-community/netinfo';
import NetworkComponent from './NetworkComponent';

// Mock different network states
const mockNetworkStates = {
  online: {
    type: 'wifi',
    isConnected: true,
    isInternetReachable: true,
    details: { ssid: 'TestWiFi' }
  },
  offline: {
    type: 'none',
    isConnected: false,
    isInternetReachable: false,
    details: null
  }
};

describe('NetworkComponent', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('should display online status when connected', async () => {
    NetInfo.useNetInfo.mockReturnValue(mockNetworkStates.online);
    
    const { getByText } = render(<NetworkComponent />);
    
    await waitFor(() => {
      expect(getByText('Connected to TestWiFi')).toBeTruthy();
    });
  });

  it('should show offline message when disconnected', async () => {
    NetInfo.useNetInfo.mockReturnValue(mockNetworkStates.offline);
    
    const { getByText } = render(<NetworkComponent />);
    
    await waitFor(() => {
      expect(getByText('No internet connection')).toBeTruthy();
    });
  });
});

7. Common Pitfalls and Solutions

Common Issues:
  • Memory Leaks: Always unsubscribe from event listeners
  • False Positives: isConnected doesn't guarantee internet access
  • iOS Simulator Issues: Test on real devices for accurate results
  • Background Limitations: iOS apps may not receive network events in background
  • Permission Requirements: WiFi SSID requires location permissions on Android

Handle Edge Cases

function RobustNetworkHandler() {
  const [networkState, setNetworkState] = useState({
    isOnline: false,
    hasInternet: false,
    connectionType: 'unknown'
  });

  useEffect(() => {
    const updateNetworkState = (state) => {
      setNetworkState({
        isOnline: state.isConnected ?? false,
        hasInternet: state.isInternetReachable ?? false,
        connectionType: state.type || 'unknown'
      });
    };

    // Handle initial state
    NetInfo.fetch()
      .then(updateNetworkState)
      .catch((error) => {
        console.error('Failed to fetch initial network state:', error);
        // Provide fallback state
        setNetworkState({
          isOnline: false,
          hasInternet: false,
          connectionType: 'unknown'
        });
      });

    const unsubscribe = NetInfo.addEventListener(updateNetworkState);
    return unsubscribe;
  }, []);

  return networkState;
}

8. Performance Optimization

Selective Updates

Optimize re-renders by selecting specific network properties:

import { useMemo } from 'react';
import { useNetInfo } from '@react-native-community/netinfo';

// Only re-render when connection status changes
function useConnectionStatus() {
  const netInfo = useNetInfo();
  
  return useMemo(() => ({
    isConnected: netInfo.isConnected,
    isInternetReachable: netInfo.isInternetReachable
  }), [netInfo.isConnected, netInfo.isInternetReachable]);
}

// Only re-render when connection type changes
function useConnectionType() {
  const netInfo = useNetInfo();
  
  return useMemo(() => netInfo.type, [netInfo.type]);
}

Lazy Network Checks

Implement lazy loading for network-dependent features:

function LazyNetworkFeature({ children }) {
  const netInfo = useNetInfo();
  const [shouldLoad, setShouldLoad] = useState(false);

  useEffect(() => {
    if (netInfo.isInternetReachable && !shouldLoad) {
      // Only load feature when internet is available
      setShouldLoad(true);
    }
  }, [netInfo.isInternetReachable, shouldLoad]);

  if (!shouldLoad) {
    return <OfflineMessage />;
  }

  return children;
}

Conclusion

React Native Community NetInfo is an essential tool for building robust, network-aware mobile applications. By following the patterns and best practices outlined in this guide, you can create apps that gracefully handle network changes, provide excellent offline experiences, and adapt to different connection qualities.

Remember to always test your network-dependent features on real devices and various network conditions. Consider implementing offline-first architecture patterns for critical app functionality, and always provide clear feedback to users about their connection status.

The library continues to evolve with new features and improvements, so stay updated with the latest releases and community contributions for the best possible user experience.

🚀 Ready to catch UI issues before your users do?

Use Viewlytics to automatically capture and analyze your app's UI across real devices. Our AI-powered platform helps you identify visual bugs, layout issues, and inconsistencies before they impact user experience.

Start UI Testing with Viewlytics
logo

2025 © Viewlytics. All rights reserved.