Internet Connection Check in React Native
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:
isConnectedonly tells you that you're connected to a network. On a WiFi network with no internet access, you'll getisConnected: truebutisInternetReachable: false. That's why we'll useisInternetReachablefor 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 justisConnected. 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: 9999keeps the banner above everything.Platform.OScheck 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:
- Installed
@react-native-community/netinfo - Built a Context + Provider structure to monitor internet status
- Showed a red banner sliding from the top when the connection drops
- Added a green notification when the connection is restored
- Used the
useInternetCheckhook 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.