← Back to Blog

Internet Connection Check in React Native

·5 min read
React NativeNetInfoProviderContext APIInternet

Internet Connection Check in React Native

One of the most common scenarios in mobile apps is the user losing their internet connection. Notifying them instantly is the simplest way to prevent a bad experience. In this post, we'll use @react-native-community/netinfo to build an InternetCheckProvider that's accessible from anywhere in the app.

What is @react-native-community/netinfo?

@react-native-community/netinfo is a React Native library that lets you monitor the device's network state. It provides:

  • Is the device connected to a network? (isConnected)
  • Is the internet actually reachable? (isInternetReachable)
  • Connection type (WiFi, Cellular, Ethernet, etc.)
  • Connection details (frequency, signal strength, etc.)

Important: isConnected only tells you that you're connected to a network. On a WiFi network with no internet access, you'll get isConnected: true but isInternetReachable: false. That's why we'll use isInternetReachable for the actual internet check.

Installation

npm install @react-native-community/netinfo

If you're using Expo:

npx expo install @react-native-community/netinfo

Don't forget the pod install for iOS:

cd ios && pod install

Building the InternetCheckProvider

Our goal: build a structure that monitors internet status app-wide, shows a warning banner sliding from the top when the connection drops, and automatically hides it when the connection is back.

1. Creating the Context

First, let's create a context to hold the internet status:

// src/contexts/InternetCheckContext.tsx
import { createContext, useContext } from "react";

interface InternetCheckContextType {
  isConnected: boolean;
}

export const InternetCheckContext = createContext<InternetCheckContextType>({
  isConnected: true,
});

export const useInternetCheck = () => useContext(InternetCheckContext);

2. The Provider Component

Now let's write the actual provider. We'll listen to connection changes using NetInfo's addEventListener method:

// src/providers/InternetCheckProvider.tsx
import React, { useEffect, useState, useCallback, useRef } from "react";
import {
  View,
  Text,
  StyleSheet,
  Animated,
  Platform,
} from "react-native";
import NetInfo, { NetInfoState } from "@react-native-community/netinfo";
import { InternetCheckContext } from "../contexts/InternetCheckContext";

interface Props {
  children: React.ReactNode;
}

export const InternetCheckProvider: React.FC<Props> = ({ children }) => {
  const [isConnected, setIsConnected] = useState(true);
  const slideAnim = useRef(new Animated.Value(-60)).current;

  const showBanner = useCallback(() => {
    Animated.timing(slideAnim, {
      toValue: 0,
      duration: 300,
      useNativeDriver: true,
    }).start();
  }, [slideAnim]);

  const hideBanner = useCallback(() => {
    Animated.timing(slideAnim, {
      toValue: -60,
      duration: 300,
      useNativeDriver: true,
    }).start();
  }, [slideAnim]);

  useEffect(() => {
    const unsubscribe = NetInfo.addEventListener((state: NetInfoState) => {
      const connected = state.isInternetReachable ?? state.isConnected ?? true;

      setIsConnected(connected);

      if (!connected) {
        showBanner();
      } else {
        hideBanner();
      }
    });

    return () => unsubscribe();
  }, [showBanner, hideBanner]);

  return (
    <InternetCheckContext.Provider value={{ isConnected }}>
      {children}
      <Animated.View
        style={[
          styles.banner,
          { transform: [{ translateY: slideAnim }] },
        ]}
      >
        <View style={styles.content}>
          <Text style={styles.icon}>📡</Text>
          <Text style={styles.text}>No internet connection</Text>
        </View>
      </Animated.View>
    </InternetCheckContext.Provider>
  );
};

const styles = StyleSheet.create({
  banner: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    backgroundColor: "#DC2626",
    paddingTop: Platform.OS === "ios" ? 50 : 30,
    paddingBottom: 12,
    paddingHorizontal: 16,
    zIndex: 9999,
  },
  content: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    gap: 8,
  },
  icon: {
    fontSize: 16,
  },
  text: {
    color: "#FFFFFF",
    fontSize: 14,
    fontWeight: "600",
  },
});

A few things to note here:

  • We use isInternetReachable, not just isConnected. This way we also catch cases where you're connected to WiFi but have no actual internet.
  • The banner slides down from the top using Animated.Value. Much better UX than an abrupt show/hide.
  • zIndex: 9999 keeps the banner above everything.
  • Platform.OS check accounts for the status bar height on iOS.

3. Integrating into the App

Wrap your app with the provider at the top level:

// App.tsx
import React from "react";
import { InternetCheckProvider } from "./src/providers/InternetCheckProvider";
import { Navigation } from "./src/navigation";

export default function App() {
  return (
    <InternetCheckProvider>
      <Navigation />
    </InternetCheckProvider>
  );
}

4. Using It in Any Screen

Now you can read the internet status from anywhere in your app:

import { useInternetCheck } from "../contexts/InternetCheckContext";

function ProfileScreen() {
  const { isConnected } = useInternetCheck();

  const handleSave = () => {
    if (!isConnected) {
      Alert.alert("Error", "Internet connection is required for this action.");
      return;
    }

    // Make API call
  };

  return (
    <View>
      <Button title="Save" onPress={handleSave} />
    </View>
  );
}

Reconnection Notification

You can also show a brief green banner when the connection comes back. Here's a small addition to the provider:

const [showReconnected, setShowReconnected] = useState(false);
const wasDisconnected = useRef(false);

useEffect(() => {
  const unsubscribe = NetInfo.addEventListener((state: NetInfoState) => {
    const connected = state.isInternetReachable ?? state.isConnected ?? true;

    if (!connected) {
      wasDisconnected.current = true;
      setIsConnected(false);
      showBanner();
    } else {
      if (wasDisconnected.current) {
        // Connection is back
        setShowReconnected(true);
        setIsConnected(true);
        showBanner();

        setTimeout(() => {
          hideBanner();
          setShowReconnected(false);
          wasDisconnected.current = false;
        }, 2000);
      } else {
        setIsConnected(true);
        hideBanner();
      }
    }
  });

  return () => unsubscribe();
}, [showBanner, hideBanner]);

Update the banner color based on state:

<Animated.View
  style={[
    styles.banner,
    {
      transform: [{ translateY: slideAnim }],
      backgroundColor: showReconnected ? "#16A34A" : "#DC2626",
    },
  ]}
>
  <View style={styles.content}>
    <Text style={styles.icon}>{showReconnected ? "✅" : "📡"}</Text>
    <Text style={styles.text}>
      {showReconnected ? "Connection restored" : "No internet connection"}
    </Text>
  </View>
</Animated.View>

NetInfo Configuration

You can customize NetInfo's reachability check:

NetInfo.configure({
  reachabilityUrl: "https://clients3.google.com/generate_204",
  reachabilityTest: async (response) => response.status === 204,
  reachabilityLongTimeout: 60 * 1000,   // 60 seconds
  reachabilityShortTimeout: 5 * 1000,   // 5 seconds
  reachabilityRequestTimeout: 15 * 1000, // 15 seconds
});

Call this configuration at the very beginning of your app, before the provider.

Summary

In this post we:

  1. Installed @react-native-community/netinfo
  2. Built a Context + Provider structure to monitor internet status
  3. Showed a red banner sliding from the top when the connection drops
  4. Added a green notification when the connection is restored
  5. Used the useInternetCheck hook to read internet status from any screen

This pattern is commonly used in production apps and significantly improves user experience. Users are informed about the connection state before they attempt any action that requires internet.