Concurrent Rendering & Suspense
The problem
Some UI updates are urgent (respond to typing immediately) and some aren't (re-render a big list after a filter changes) — treating every update with equal priority means a slow, low-priority update can block a fast, high-priority one, and waiting for slow data to load has traditionally meant either a blank screen or manual loading-state plumbing everywhere.
Why now
Fiber's interruptible work model made it structurally possible to pause and prioritize renders; concurrent rendering and Suspense are the features actually built on top of that possibility — turning 'renders are technically interruptible' into 'React can decide what to render first, and pause a component that isn't ready yet without you writing that logic by hand.'
Mental model
Concurrent rendering lets React prepare multiple versions of the UI and prioritize which to show — an urgent update (typing) can interrupt an in-progress, less urgent one (a big re-render) rather than waiting behind it. Suspense lets a component 'pause' rendering while it's waiting on something (usually data) by throwing a promise React catches, showing a fallback until it resolves — the same idea as a loading spinner, but handled by the rendering system itself instead of manual isLoading state threaded through every component.
Requires
- React Fiber ArchitectureReact
Concurrent rendering and Suspense both depend on the interruptible, resumable unit-of-work model Fiber introduced; without that foundation, pausing a render for a higher-priority update or a pending promise isn't structurally possible.
Helps
- The Event LoopJavaScript Runtime
Concurrent rendering's prioritization decisions interact directly with the browser's own task scheduling already covered — React is essentially negotiating with the same event loop for a chance to paint urgent updates first.
Unlocks
Used in
- useTransition and useDeferredValue for marking updates as lower priority
- <Suspense> boundaries showing a fallback while lazy-loaded components or data are pending
- Data-fetching libraries and frameworks (Next.js) integrating with Suspense for loading states
- Keeping an app's input responsiveness high even during expensive re-renders
Projects
- Wrap an expensive list re-render in useTransition and demonstrate that typing in a search box stays responsive while the list update is deprioritized
- Wrap a data-fetching component in a <Suspense> boundary and observe the fallback UI display automatically while the fetch is pending, with no manual isLoading state
Examples
- Typing in a filter input stays smooth even while a 10,000-item list re-renders, because useTransition tells React the list update can be interrupted
- <Suspense fallback={<Spinner />}><ProfilePage /></Suspense> shows the spinner automatically until ProfilePage's data dependencies resolve, without hand-written loading state
Resources
Mastery checklist
- I can use useTransition to deprioritize a non-urgent update and keep the UI responsive
- I can wrap a component in Suspense and explain what triggers the fallback
- I can explain how Suspense replaces manually threaded isLoading state
- I can explain the relationship between concurrent rendering and Fiber's interruptibility