A resilient app reacts to the network: show an "offline" banner when the connection drops, queue writes until it's back, or drop to lower-res images on a slow 2g link. The browser exposes this through two APIs — navigator.onLine plus the online/offline events for connectivity, and the Network Information API (navigator.connection) for quality (effectiveType, downlink, rtt, saveData). useNetworkState reads both and re-renders when either changes.
Implement useNetworkState(). Return { online, effectiveType, downlink, rtt, saveData, type }, seeded on mount, updated on the online/offline window events and the connection's change event, and cleaned up on unmount. Degrade gracefully where navigator.connection isn't supported.
function useNetworkState() {
// returns { online, effectiveType, downlink, rtt, saveData, type }
}
const { online, effectiveType } = useNetworkState();
if (!online) return <OfflineBanner />;
const lowData = effectiveType === '2g' || effectiveType === 'slow-2g';
const { saveData } = useNetworkState();
<Image src={saveData ? lowRes : highRes} />
navigator.onLine (+ online/offline events) for connectivity; navigator.connection for quality.online, offline, and (if present) the connection's change event, re-reading all fields in one handler.undefined when navigator.connection is missing, but still report online.