Skip to content
Advanced8 min study

Suspense

Coordinate pending UI, progressive reveal, transitions, streaming, caching, and error boundaries with Suspense.

Question progress0 / 10 completed
Start the lesson
Suspense visual explanation

WHAT YOU WILL BE ABLE TO DO

Learning outcomes

  • Explain suspense in plain language.
  • Connect the behavior to the underlying browser or framework model.
  • Implement the core pattern and reason through edge cases.
  • Answer common follow-ups without relying on memorized phrases.

01Overview

Suspense lets a component tree declare a fallback for when part of it isn't ready — code still loading, or data still fetching — instead of every component threading its own isLoading flag through props and state.

02Mental model

Internally, a resource that isn't ready throws a promise; the nearest Suspense boundary catches it, renders the fallback, and re-renders the real tree once that promise resolves. React.lazy uses this mechanism for code-splitting; data-fetching frameworks that integrate with Suspense use it for data.

03Examples

JavaScript
const Settings = React.lazy(() => import('./Settings'));
function App() {  return (    <Suspense fallback={<Spinner />}>      <Settings />    </Suspense>  );}

04Check understanding

Can a plain fetch inside useEffect be suspended by wrapping the component in Suspense?

Not on its own — a component only suspends if it throws a promise in a way Suspense understands (React.lazy, or a data layer explicitly built for it), not simply because a network request happens somewhere inside it.

DDConcept deep dives

Deep dive 1

A boundary coordinates pending descendants

When compatible descendant work cannot complete, React finds the nearest Suspense boundary and renders its fallback. Suspense defines how loading is grouped and revealed; the framework or data layer defines how a read integrates with suspension and caching. Creating an ordinary fetch inside render is not automatically a supported Suspense data source.

  • Pending work goes to Suspense; rejected work goes to an Error Boundary.
  • Fallbacks should preserve context and layout instead of blanking the whole page.
  • Boundary placement is a product loading decision as much as a technical one.

Deep dive 2

Transitions preserve already useful UI

If an update may suspend, marking it as a transition tells React that the new result is non-urgent. Urgent input can update immediately while existing content remains visible until replacement content is ready, often with a subtle pending indicator. This avoids repeatedly replacing a usable interface with a large spinner.

  • Do not put the controlled input update itself inside a transition.
  • A transition does not make slow computation free; reduce or move the work.
  • Pending indicators must remain perceivable without causing disruptive layout shifts.

Deep dive 3

Caching defines consistency

A suspending read must encounter the same pending record on repeated renders rather than create new work indefinitely. The cache determines deduplication, freshness, invalidation, and how server and client data connect. Framework APIs are preferable to inventing an undocumented global promise cache with no lifecycle.

  • Cache keys include every input that changes the resource.
  • Invalidation should be tied to mutations and freshness requirements.
  • Streaming boundaries and caches must avoid revealing mutually inconsistent data.

QAInterview questions and model answers

Attempt each answer aloud before opening it. The model answer shows the depth and precision expected in an interview; it is not a script to memorize.

Intermediate · Coding · 1 min · Question 1What does Suspense do?Open model answer

Model answer

Suspense coordinates a fallback while descendant work declares that it is not ready. It is a boundary for loading and reveal behavior, not a general-purpose data-fetching API by itself. Framework integration determines which data sources can suspend.

JSX
<Suspense fallback={<Spinner />}>  <Profile />        {/* suspends while its data/code loads */}  <Feed /></Suspense>
Open question page →
Intermediate · Coding · 1 min · Question 2Does Suspense catch errors?Open model answer

Model answer

No. A rejected operation is handled by an error boundary, while Suspense handles pending work. Production trees often place loading and error boundaries together with scopes chosen for independent recovery.

JSX
<ErrorBoundary fallback={<RetryPanel />}>  <Suspense fallback={<Spinner />}>    <Report />  </Suspense></ErrorBoundary>
Open question page →
Intermediate · Conceptual · 1 min · Question 3How should Suspense boundaries be placed?Open model answer

Model answer

Place them around content that can load and reveal together without hiding already useful UI. Many tiny boundaries create flicker and complexity; one enormous boundary delays everything. Product loading sequences should drive placement.

Open question page →
Advanced · Coding · 1 min · Question 4What happens when already visible content suspends during an update?Open model answer

Model answer

React may show the nearest fallback unless the update is marked non-urgent, for example with a transition, allowing current content to remain while new content prepares. The exact experience depends on boundary and cache behavior.

JSX
const [isPending, startTransition] = useTransition();startTransition(() => setQuery(next)); // keep old results visible,                                       // isPending drives a subtle spinner
Open question page →
Intermediate · Conceptual · 1 min · Question 5Why must a Suspense data source cache its promise?Open model answer

Model answer

Creating a new promise on every render can cause repeated suspension and duplicate work. A compatible cache gives repeated reads the same pending or fulfilled record and defines invalidation semantics.

Open question page →
Intermediate · Conceptual · 1 min · Question 6How does Suspense help server rendering?Open model answer

Model answer

Boundaries let a server stream completed regions independently and let the client hydrate progressively. A useful fallback should preserve layout and meaning while slower content arrives.

Open question page →
Advanced · Conceptual · 1 min · Question 7Can a Suspense fallback itself suspend?Open model answer

Model answer

Yes. React searches upward for the next Suspense boundary capable of showing a fallback, so fallback dependencies and boundary nesting require deliberate design.

Open question page →
Advanced · Conceptual · 1 min · Question 8Does startTransition delay the state update by a fixed time?Open model answer

Model answer

No. It marks update priority as non-urgent, letting React interrupt and schedule rendering while urgent work such as controlled input remains responsive.

Open question page →
Advanced · Conceptual · 1 min · Question 9What is a SuspenseList?Open model answer

Model answer

It is an experimental or renderer-dependent coordination concept for reveal order, not a stable universal API to assume in ordinary production React without verifying support.

Open question page →
Advanced · Conceptual · 1 min · Question 10Where should an Error Boundary sit relative to Suspense?Open model answer

Model answer

Place boundaries according to independent loading and recovery scopes. A region often needs both so rejection shows actionable error UI without taking down unrelated content.

Open question page →

SCScenario questions

Scenario 1

Navigating between tabs replaces the entire panel with a spinner on every keystroke-driven filter.

  1. Separate urgent input state from non-urgent result updates.
  2. Keep previous useful results visible during transition where appropriate.
  3. Place the boundary around results rather than input controls.
  4. Use a stable cache and accessible pending indicator.
Reveal worked answer

I would update the input urgently and start the result change as a transition. The existing results can remain visible with a subtle pending state while the new resource prepares. The Suspense boundary surrounds only replaceable results, so controls never disappear.

Verify and go deeper