state
useSyncExternalStore
Subscribes a component to an external store in a way that is safe with concurrent rendering, preventing tearing. Reach for it when writing a library or reading from a store that lives outside React (Redux, Zustand, browser APIs, custom event emitters).
const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?) Parameters & Behavior
| Parameter | Purpose |
|---|---|
| subscribe | (onStoreChange) => unsubscribe — React calls onStoreChange when the store changes |
| getSnapshot | Returns the current store value; must be referentially stable when unchanged |
| getServerSnapshot | Snapshot used during SSR — required if you server-render this component |
| tearing-free | All consumers see the same value within a single render pass |
Examples
const width = useSyncExternalStore(
(cb) => { window.addEventListener('resize', cb); return () => window.removeEventListener('resize', cb); },
() => window.innerWidth,
() => 0
); Read window width with SSR-safe fallback
const online = useSyncExternalStore(
(cb) => { window.addEventListener('online', cb); window.addEventListener('offline', cb); return () => { window.removeEventListener('online', cb); window.removeEventListener('offline', cb); }; },
() => navigator.onLine,
() => true
); Track online/offline state safely
function useStore(selector) {
return useSyncExternalStore(store.subscribe, () => selector(store.getState()), () => selector(store.getInitialState()));
} Selector hook pattern used by lightweight state libraries
const theme = useSyncExternalStore(mediaSubscribe, () => mql.matches ? 'dark' : 'light'); Reactively read a matchMedia query
Gotcha
getSnapshot must return the SAME reference when the underlying value hasn't changed — recreating objects inside it causes an infinite render loop. Provide getServerSnapshot whenever the component might be server-rendered.
Related hooks
useState
Declares a piece of local state in a function component and returns the current value along with a setter. Reach for it whenever a component needs to remember a value across renders and re-render when that value changes.
useEffect
Runs a side effect after the browser has painted the committed render. Reach for it for subscriptions, data fetching, DOM syncing with external systems, timers, and anything that must not block the visual update.
useContext
Reads the current value of a React context from the nearest matching Provider above in the tree. Reach for it to share values like themes, auth, or locale without prop-drilling through every intermediate component.
useReducer
Manages component state through a reducer function that maps (state, action) to the next state. Reach for it when state transitions are complex, involve multiple sub-values, or when the next state depends on the previous in non-trivial ways.