Capítulo 64 de 116
useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?) is the correct way to read a value from a store outside React (a third-party state library, a browser API) that can change on its own — it guarantees the component re-renders on every store change and never tears (shows inconsistent values) even under concurrent rendering.
subscribe(callback) registers callback to run whenever the store changes and returns an unsubscribe function; getSnapshot() returns the store's current value (must return a cached/stable reference if nothing changed, not a fresh object every call); optional getServerSnapshot() provides the value to use during server rendering.useEffect + useState: subscribing manually via useEffect and mirroring the external value into useState is a common pattern for external stores, but it can "tear" under React's concurrent rendering — different parts of the tree could momentarily read different values of the same external store mid-render. useSyncExternalStore is specifically built to prevent that.getSnapshot must be cheap and stable: called on every render (and more, internally, for tear-checking) — it must return the same reference if the underlying data hasn't changed, or the Hook will think the store changed and force extra re-renders.useSyncExternalStore internally (state management libraries, routers) — writing a raw call by hand is comparatively rare in app code.getServerSnapshot is required for SSR-rendered components reading an external store — without it, React throws during server rendering since there's no way to know what value to use before the client's store exists.function useOnlineStatus() {
return useSyncExternalStore(
(callback) => {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
},
() => navigator.onLine, // client snapshot
() => true // server snapshot
);
}
navigator.onLine) safely, with a server-side fallback snapshot.getSnapshot returning a fresh object/array every call is a common bug — it must be referentially stable when the store hasn't changed.useOnlineStatus).useEffect-based alternative this Hook improves on for tear-safety.