useSyncExternalStore

useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?) reads a value from a store that lives outside React, and re-renders the component whenever that store changes. subscribe takes a callback, hooks it up to the store's own change notifications, and returns an unsubscribe function; call the callback whenever the store changes, and React re-runs getSnapshot to check for an update. getSnapshot just reads and returns the store's current value – cheaply, since it may be called often – and must keep returning an equal value (compared with Object.is) for as long as nothing has actually changed, or React will conclude the store changed on every check and re-render in a loop.

The optional third argument, getServerSnapshot, supplies the value to use during server rendering and hydration. It isn't needed for the client-only demo below, but leaving it out does make server rendering throw for a component that calls this Hook.

This Hook is React's answer to a problem older than Hooks themselves: safely reading mutable data that React doesn't own – a browser API, a third-party store, an old Backbone model – from inside a render. The previous way of doing this was to subscribe inside a useEffect and force a re-render by hand; that works most of the time, but under React's concurrent rendering a store can mutate mid-render and leave different parts of the tree reading different values, a class of bug usually called "tearing". useSyncExternalStore is built specifically to avoid it.

Toggle your network connection (or, in DevTools' Network panel, the "Offline" throttling checkbox) to see this update live — no polling involved; React re-renders only when the 'online'/'offline' window events actually fire.
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}
function getSnapshot() {
  return navigator.onLine;
}
function useOnlineStatus() {
  return React.useSyncExternalStore(subscribe, getSnapshot);
}
function App() {
  const isOnline = useOnlineStatus();
  return <p>Status: {isOnline ? 'Online' : 'Offline'}</p>;
}
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<App/>);
</script>
</body></html>