Concurrent Store

Navigating before the data arrives

You will learn

A router changes the route inside startTransition, so React keeps the current screen on the page until the next one is ready. Both columns below dispatch exactly that way, through the same reducer. They differ only in the Hook that reads the route.

Try it

  1. Click Go to profile. Its data is held open, so the navigation stays in flight until you release it.
  2. Click Like Ada’s post while you wait, then Profile data arrives.

Notice that the left column loses the feed as soon as you navigate. A component reading the store with useSyncExternalStore opts the Transition out, so React commits the route immediately, the profile has no data yet, and the Suspense boundary replaces the page.

The right column stays on the feed and stays interactive. Your like lands on the post you are looking at, not on the profile that has not loaded, and both updates are in the order you made them once the profile arrives.

That first behaviour is a documented caveat of useSyncExternalStore: a store update during a Transition makes React flush it synchronously. The caller already said what it wanted by calling startTransition. Only the reading Hook discards it.

useSyncExternalStoreblocking
app/home
AAda LovelaceNotes on the analytical engine
GGrace HopperFound an actual moth
AAlan TuringHalting, eventually

Reads the route the way store libraries read one today.

useStoretransition
app/home
AAda LovelaceNotes on the analytical engine
GGrace HopperFound an actual moth
AAlan TuringHalting, eventually

Reads the route with useStore.