Suspense & deferred values
Type into the search field and watch the two panels side by side.
- Left (
useSyncObservable) — each keystroke is a synchronous store update. When results suspend, React replaces already-visible content with the Suspense fallback (and may log “A component suspended while responding to synchronous input” — open Sandpack’s console). - Right (
useObservable) — store updates are deferred. Already-revealed results stay on screen (dimmed while stale) until the new ones are ready. - The input itself reads
useSyncObservableso typing never lags — this is exactly when you need the sync hook.
Why this happens
useSyncExternalStore cannot mark store mutations as Transitions, so suspending on its value triggers the nearest Suspense fallback. Wrapping the value in useDeferredValue (what useObservable does) is how you prevent unwanted fallbacks for already-revealed content.
See also jantimon/react-hydration-rules for the broader hydration/Suspense matrix, and the React reconciler tests for useDeferredValue / useSyncExternalStore in facebook/react . Hydration-time differences between the two hooks are covered by the library’s Vitest suite (Sandpack examples are client-only).
Last updated on