Skip to content

Concurrent React & Suspense

Older React rendered every update synchronously and to completion — once it started, it could not stop, so a big re-render would block the browser and freeze typing. Concurrent React changes that: rendering is interruptible. React can start rendering an update, pause it to handle something more urgent, and resume later.

The insight is that some updates are urgent (typing into an input must feel instant) and some are non-urgent (re-filtering a huge list, loading a new page). Concurrent features let you tell React which is which, so the urgent work is never blocked by the heavy work.

LessonWhat you’ll learn
TransitionsuseTransition and useDeferredValue — keep the UI responsive
Suspense & lazyDeclarative loading UI and code-splitting with React.lazy
Error boundariesCatching render errors, and pairing with Suspense
use() & data fetchingThe React 19 use() hook and render-as-you-fetch
flowchart TB
  urgent["Urgent update
(keystroke)"] --> render1["render immediately
(never blocked)"]
  nonurgent["Non-urgent update
(filter big list)"] --> render2["render in the background
(interruptible)"]
  urgent -.interrupts.-> render2
Urgent updates interrupt non-urgent ones

You mark the heavy update as non-urgent (a transition), and React renders it in the background where a keystroke can interrupt it. Suspense then handles the case where part of the tree isn’t ready yet (it’s loading data or code), showing a fallback declaratively instead of you juggling loading booleans.

What does "concurrent" rendering allow that older synchronous rendering did not?
How do you tell React which updates are non-urgent?
What does Suspense handle?