Suspense and Concurrent Rendering in React
Concurrent rendering lets React work on an update without necessarily blocking already visible UI. When rendering encounters a suspended subtree, Suspense can show fallback content while React prepares the suspended UI.
Concurrent rendering is a rendering capability in React that allows work to be interrupted, continued, or abandoned before it is committed to the DOM. This is different from making JavaScript execution literally parallel: rendering work still runs on the JavaScript thread, but React can schedule it more flexibly.
Suspense defines what React should display when a descendant cannot finish rendering yet. A common case is a component that suspends while waiting for data or code. React can keep the current committed UI visible and render the nearest appropriate Suspense fallback or, depending on the update and boundary state, preserve already visible content while the new tree becomes ready.
The important distinction is between rendering and committing. React may start rendering a new tree, pause that work, and later resume or discard it. DOM mutations happen during commit, so unfinished concurrent work does not partially appear in the browser.
Transitions are commonly used with Suspense when an update should be treated as non-urgent. For example, changing a selected tab can update an input immediately while React prepares the new tab content in the background. APIs such as `startTransition` communicate that distinction to React; Suspense boundaries determine what can be shown if the transition encounters suspended content.
Key points
- Concurrent rendering makes rendering work interruptible and schedulable; it does not mean React renders on multiple JavaScript threads.
- Suspense provides boundaries for UI that cannot complete rendering immediately.
- React separates render work from the commit phase, so unfinished render work is not partially committed.
- `startTransition` marks an update as non-urgent so urgent interactions can remain responsive.
- A good Suspense boundary is both a loading-state boundary and a unit of UI that can be revealed together.
Interview questions
What does concurrent rendering mean in React?
Concurrent rendering means React can work on rendering an update in an interruptible way rather than treating the entire render as an indivisible operation. React can pause work, continue it later, or discard it if newer work makes it unnecessary. This improves scheduling of urgent and non-urgent UI work. It does not mean that React performs rendering simultaneously on multiple JavaScript threads.
How do Suspense and concurrent rendering work together?
A Suspense boundary identifies a part of the tree that may not be ready to render immediately. If that subtree suspends, React can render the boundary's fallback or otherwise preserve appropriate already-visible content while work continues. Concurrent rendering makes it possible to prepare the next UI without requiring the current committed UI to be synchronously replaced. The boundary therefore provides the UI behavior, while concurrent rendering provides flexible scheduling of the work.
Why would you use `startTransition` around a state update?
`startTransition` tells React that the enclosed update is non-urgent. React can prioritize more urgent interactions, such as typing or clicking, while preparing the transition update. If the transition encounters suspended content, Suspense boundaries can coordinate what the user sees during that preparation. The API is therefore about update priority, not about creating a separate thread.
Why is the distinction between render and commit important for concurrent rendering?
The render phase determines what the next UI should look like, while the commit phase applies the completed result to the host environment. Concurrent rendering primarily makes render work interruptible. React can therefore discard an incomplete render without exposing an inconsistent partial tree in the DOM. Code with side effects should not rely on render running exactly once because render work can be restarted or abandoned.
How would you choose a Suspense boundary location?
A boundary should correspond to a meaningful unit of UI that can load or reveal together. A boundary that is too high can replace too much already-useful content with a fallback, while one that is too low can create fragmented loading states. The desired reveal sequence and user experience should guide the placement. In larger applications, framework-level data loading and routing behavior may also influence the appropriate boundaries.