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
- Wrap the part of the UI that can wait in
<Suspense>. - Choose a fallback with the same approximate footprint as the final content.
- Place boundaries around meaningful sections, not every tiny child.
- Use nested boundaries when content can reveal in stages.
- 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> );}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> );}Summary
4 active projects
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
fetchin 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
- Previous: Part 11: Custom hooks as reuse boundaries
- Next: Part 13: Transitions for responsive updates
- Series index: Modern React development