BEGINNERREACTHOOKS

useOnlineStatus Hook for React

A typed React hook that tracks the browser online/offline state and re-renders components when the network status changes.

Published May 8, 2026
reacthooksonlinenetworkoffline

useOnlineStatus is a React hook that returns true when the browser has a network connection and false when it doesn't. It listens to the online and offline events on window and re-renders consumers automatically. Use it to show offline banners, queue API calls, or disable submit buttons during disconnects.

Tested on React 19, modern browsers.

When to Use This

  • Showing an "offline" banner when the user loses connection
  • Disabling form submit buttons during network outages
  • Switching to a cached/local data source when offline
  • Triggering retry logic when connection comes back

Don't use this when you need ground-truth API reachability (use a real heartbeat to your server) or when the entire app is offline-first (use a service worker with proper sync).

Code

import { useEffect, useState } from 'react';
 
export function useOnlineStatus(): boolean {
  // SSR-safe default: assume online so we don't flash an offline banner
  const [online, setOnline] = useState<boolean>(() =>
    typeof navigator === 'undefined' ? true : navigator.onLine
  );
 
  useEffect(() => {
    const handleOnline = () => setOnline(true);
    const handleOffline = () => setOnline(false);
 
    // Sync with current state in case it changed before listeners attached
    setOnline(navigator.onLine);
 
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
 
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);
 
  return online;
}

The lazy initializer in useState checks for navigator so it works during server rendering. The setOnline(navigator.onLine) inside the effect re-syncs in case the user went offline between mount and effect run.

Usage

An offline banner that appears at the top of the app:

'use client';
 
import { useOnlineStatus } from '@/hooks/useOnlineStatus';
import { WifiOff } from 'lucide-react';
 
export function OfflineBanner() {
  const online = useOnlineStatus();
 
  if (online) return null;
 
  return (
    <div className="fixed top-0 inset-x-0 bg-amber-500 text-white px-4 py-2 flex items-center gap-2 z-50">
      <WifiOff className="h-4 w-4" />
      <span>You are offline. Some features may not work.</span>
    </div>
  );
}

The banner only renders when offline, which avoids any visual cost while online.

Things to Know

  • navigator.onLine is famously unreliable. It only knows whether the browser has a network interface, not whether your servers are reachable. A captive portal looks "online" to the browser.
  • Don't use this as your only retry trigger. Combine it with actual fetch error handling. Some failures (DNS, CORS, server down) happen while online.
  • The online and offline events fire only on transitions. If the user starts the page offline, the events won't fire — that's why we re-sync inside the effect.
  • Mobile browsers throttle background tabs. A backgrounded tab may not receive offline events until it's foregrounded again.
  • Don't use this for connectivity-aware features that need precise timing. Use the Network Information API for downlink speed and effective connection type.

Frequently Asked Questions

How accurate is navigator.onLine?

navigator.onLine reports whether the browser thinks it has a network connection, but it doesn't verify reachability to your actual server. A user could be on Wi-Fi (online: true) but unable to reach your API. Treat it as a hint, not a guarantee.

Does useOnlineStatus work with SSR?

Yes, but the initial render uses a sensible default (true) because navigator is undefined on the server. The real value updates on the first client effect. This avoids hydration mismatches.

X (Twitter)LinkedIn