useSyncExternalStore
React chapter 18 · React 18 · useMediaQuery · source: react.dev/reference/react/useSyncExternalStore
The problem
Reading a store from useEffect means the first render uses a guess. The screen shows the wrong value for one render, then fixes itself.
The pattern that fixes it
useSyncExternalStore(subscribe, getSnapshot) reads the store during render, so the first render already has the right value. MUI useMediaQuery is built on it.
In plain words
Some data lives outside React: the browser window size, a saved setting, a Redux store. To show it, React has to ask the store for its value and be told when it changes. This hook does both in one step.
A wall clock in the hallway is not yours. With useEffect you glance at it only after you have already told everyone the time was 12:00. With this hook you glance first, then speak.
Terms
- external store
- Data that lives outside React state: window, localStorage, a Redux store, any object you own.
- subscribe
- A function that says "call me when the store changes" and returns a way to stop listening.
- snapshot
- The store value right now. It must be the same value (same identity) until the store really changes.
Going deeper
How does it work?
During render React calls getSnapshot() and uses the result. It subscribes after the component commits. When the store calls your callback, React calls getSnapshot() again and re-renders only if the value is different by Object.is. React also re-checks the snapshot before finishing a render, so concurrent rendering cannot show half old, half new data ("tearing").
Pitfalls and when it does nothing
getSnapshot must return a cached value. If it builds a new object or array on every call, React sees a change each time and loops forever. For server rendering, pass a third argument getServerSnapshot that returns the same value the server used, otherwise hydration warns. If a store never changes, a plain constant is enough and you do not need this hook.
When not to use it
Data that belongs to one component is just useState. A value you can compute from props or state is plain code. Libraries (Redux, Zustand, useMediaQuery) already use this hook inside, so you rarely write it by hand; reach for it when you build your own small store or wrap a browser API.
Keep learning
- Previous: useDeferredValue
- Next: use + Suspense
- Related: memo
- Related: useMemo
- Related: useCallback
- Related: Custom hooks
- Related: useEffectEvent
- Related: useTransition
More courses
- Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
- Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
- Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
- System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
- Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
- Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
- Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
- CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
- Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
- Docker — What an image is, why layers cache, and how containers find each other on a network.
- Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.