Skip to content

Modern React 12: Data loading with Suspense boundaries

This is part 12 of the Modern React development series.

Suspense gives loading UI a place in the component tree. Instead of one global spinner or scattered conditional branches, a Suspense boundary says which part of the page can wait and what should appear while it waits.

Concept

<Suspense> renders a fallback while a child is not ready because code or data suspended during rendering. A Suspense boundary controls reveal order and keeps loading states close to the UI they replace.

Terms

  • Suspense boundary: A <Suspense> component that catches suspended children and shows a fallback.
  • Fallback: The temporary React node shown while children are loading.
  • Suspend: The act of telling React that rendering cannot finish until a Promise-like value resolves.
  • Reveal order: The sequence in which nested loading regions become visible.

Mental model

Think of Suspense as a curtain around one section of the stage. That section can stay behind a placeholder until its actors and props are ready, while the rest of the page can keep showing.

How it is used

Suspense is used for lazy-loaded components, framework data loading, streaming server rendering, nested route loading states, and client components that read a Promise with React’s use API.

How to use it

  1. Wrap the part of the UI that can wait in <Suspense>.
  2. Choose a fallback with the same approximate footprint as the final content.
  3. Place boundaries around meaningful sections, not every tiny child.
  4. Use nested boundaries when content can reveal in stages.
  5. Use framework data APIs when the framework owns Suspense data integration.

Example: Boundary around a data section

import { Suspense } from "react";
import { Albums, AlbumsSkeleton, ArtistHeader } from "./ArtistPanels";
export function ArtistPage({ artistId }: { artistId: string }) {
return (
<main>
<ArtistHeader artistId={artistId} />
<Suspense fallback={<AlbumsSkeleton />}>
<Albums artistId={artistId} />
</Suspense>
</main>
);
}
React output

Artist maya

  • Live set for maya
  • Studio sessions

The header can render independently while the albums section waits behind its own skeleton.

Example: Nested reveal

import { Suspense } from "react";
import { ChartSkeleton } from "./ChartSkeleton";
import { PageShellSkeleton } from "./PageShellSkeleton";
import { RevenueChart } from "./RevenueChart";
import { SummaryCards } from "./SummaryCards";
export function Dashboard() {
return (
<Suspense fallback={<PageShellSkeleton />}>
<SummaryCards />
<Suspense fallback={<ChartSkeleton />}>
<RevenueChart />
</Suspense>
</Suspense>
);
}
React output

Summary

4 active projects

Revenue by week
$42k, $48k, $53k

Nested boundaries let the shell and summary reveal separately from heavier chart content.

Details to watch

  • Data source: Suspense for data depends on framework or library integration. A plain fetch in a client component is not enough by itself.
  • Fallback churn: Transitions and deferred values can keep already revealed content from being replaced by a fallback during non-urgent updates.
  • State reset: Content that suspends before first mount does not preserve state from that abandoned render.
  • Boundary size: A boundary should map to a user-meaningful loading region.

Series navigation

References