Fiber UI LogoFiberUI

useNetwork

A hook that monitors network connectivity status. Provides real-time updates on online/offline state and connection details like effective type and downlink speed.

Installation

npx shadcn@latest add https://r.fiberui.com/r/hooks/use-network.json

A hook to monitor the user's network connection state. It provides online/offline status and estimates for bandwidth, latency, and connection type (where supported by the browser).

Browser Support

The online status is widely supported. However, connection details (downlink, rtt, etc.) are primarily supported in Chromium-based browsers via the Network Information API.

Source Code

View the full hook implementation in the Hook Source Code section below.

Basic Status Indicator

A simple online/offline indicator using the online property.

You are online

Connection is active

"use client";

import { useNetwork } from "@repo/hooks/device/use-network";
import { Wifi, WifiOff } from "lucide-react";

export const Example1 = () => {
    const { online } = useNetwork();

    return (
        <div
            className={`flex items-center gap-3 rounded-lg border p-4 ${
                online
                    ? "border-green-500/50 bg-green-500/10 text-green-700 dark:text-green-400"
                    : "text-destructive border-red-500/50 bg-red-500/10"
            }`}
        >
            <div
                className={`flex h-10 w-10 items-center justify-center rounded-full ${
                    online ? "bg-green-500/20" : "bg-red-500/20"
                }`}
            >
                {online ? (
                    <Wifi className="h-5 w-5" />
                ) : (
                    <WifiOff className="h-5 w-5" />
                )}
            </div>
            <div>
                <p className="text-sm font-medium">
                    {online ? "You are online" : "You are offline"}
                </p>
                <p className="text-xs opacity-80">
                    {online
                        ? "Connection is active"
                        : "Check your internet connection"}
                </p>
            </div>
        </div>
    );
};

Network Dashboard

Visualizing detailed connection metrics like bandwidth estimate and effective connection type.

Speed (Downlink)
--
Connection Type
--
Latency (RTT)
--
Data Saver
Off
"use client";

import { useNetwork } from "@repo/hooks/device/use-network";
import { Activity, Radio, Zap, Globe } from "lucide-react";

export const Example2 = () => {
    const { online, downlink, effectiveType, rtt, saveData } = useNetwork();

    if (!online) {
        return (
            <div className="text-muted-foreground w-full rounded-lg border border-dashed p-8 text-center text-sm">
                Connect to the internet to see details
            </div>
        );
    }

    return (
        <div className="grid w-full grid-cols-2 gap-4 sm:grid-cols-2">
            <div className="flex flex-col gap-1 rounded-lg border p-4">
                <div className="text-muted-foreground flex items-center gap-2 text-xs">
                    <Activity className="h-3.5 w-3.5" />
                    Speed (Downlink)
                </div>
                <div className="text-2xl font-bold tabular-nums">
                    {downlink ? `${downlink} Mbps` : "--"}
                </div>
            </div>

            <div className="flex flex-col gap-1 rounded-lg border p-4">
                <div className="text-muted-foreground flex items-center gap-2 text-xs">
                    <Radio className="h-3.5 w-3.5" />
                    Connection Type
                </div>
                <div className="text-2xl font-bold uppercase tabular-nums">
                    {effectiveType || "--"}
                </div>
            </div>

            <div className="flex flex-col gap-1 rounded-lg border p-4">
                <div className="text-muted-foreground flex items-center gap-2 text-xs">
                    <Globe className="h-3.5 w-3.5" />
                    Latency (RTT)
                </div>
                <div className="text-2xl font-bold tabular-nums">
                    {rtt ? `${rtt} ms` : "--"}
                </div>
            </div>

            <div className="flex flex-col gap-1 rounded-lg border p-4">
                <div className="text-muted-foreground flex items-center gap-2 text-xs">
                    <Zap className="h-3.5 w-3.5" />
                    Data Saver
                </div>
                <div className="text-2xl font-bold">
                    {saveData ? "On" : "Off"}
                </div>
            </div>
        </div>
    );
};

API Reference

Hook Signature

function useNetwork(): NetworkState;

NetworkState

NameTypeDescription
onlinebooleantrue if the device is connected to the internet, false otherwise.
downlinknumber | undefinedEffective bandwidth estimate in megabits per second.
downlinkMaxnumber | undefinedMaximum downlink speed of the underlying connection technology.
effectiveTypestring | undefinedEffective connection type: 'slow-2g', '2g', '3g', or '4g'.
rttnumber | undefinedEstimated effective round-trip time in milliseconds.
saveDataboolean | undefinedtrue if the user has requested a reduced data usage mode.
typestring | undefinedTheoretical connection type (e.g., 'bluetooth', 'cellular', 'wifi').

Hook Source Code

import { useState, useEffect } from "react";

export interface NetworkState {
    /** Whether device is online */
    online: boolean;
    /** Effective bandwidth estimate in Mbps */
    downlink?: number;
    /** Max downlink speed */
    downlinkMax?: number;
    /** Effective connection type ('slow-2g', '2g', '3g', or '4g') */
    effectiveType?: "slow-2g" | "2g" | "3g" | "4g";
    /** Round-trip time estimate in ms */
    rtt?: number;
    /** Whether user has requested reduced data usage */
    saveData?: boolean;
    /** Connection type (wifi, cellular, etc.) */
    type?: string;
}

// Network Information API types
interface NetworkInformation extends EventTarget {
    downlink?: number;
    downlinkMax?: number;
    effectiveType?: "slow-2g" | "2g" | "3g" | "4g";
    rtt?: number;
    saveData?: boolean;
    type?: string;
    onChange?: (e: Event) => void;
}

// Add to navigator interface
declare global {
    interface Navigator {
        connection?: NetworkInformation;
        mozConnection?: NetworkInformation;
        webkitConnection?: NetworkInformation;
    }
}

/**
 * A React hook that tracks network status and connection details.
 *
 * @returns NetworkState object containing online status and connection info
 */
export function useNetwork(): NetworkState {
    const [state, setState] = useState<NetworkState>({
        online: true, // Default to true for SSR safety
    });

    useEffect(() => {
        const isSupported =
            typeof navigator !== "undefined" &&
            (navigator.connection ||
                navigator.mozConnection ||
                navigator.webkitConnection);

        const connection = isSupported
            ? navigator.connection ||
              navigator.mozConnection ||
              navigator.webkitConnection
            : null;

        const updateState = () => {
            const online = navigator.onLine;

            if (!connection) {
                setState((prev) => ({ ...prev, online }));
                return;
            }

            setState({
                online,
                downlink: connection.downlink,
                downlinkMax: connection.downlinkMax,
                effectiveType: connection.effectiveType,
                rtt: connection.rtt,
                saveData: connection.saveData,
                type: connection.type,
            });
        };

        // Initial update
        updateState();

        // Listeners for online/offline
        window.addEventListener("online", updateState);
        window.addEventListener("offline", updateState);

        // Listener for connection changes
        if (connection) {
            connection.addEventListener("change", updateState);
        }

        return () => {
            window.removeEventListener("online", updateState);
            window.removeEventListener("offline", updateState);
            if (connection) {
                connection.removeEventListener("change", updateState);
            }
        };
    }, []);

    return state;
}