All topics
Advancedadvanced

Suspense for Data Fetching

Learn how Suspense extends beyond code splitting to coordinate loading states for asynchronous data, not just lazy-loaded components.

Beyond its original use with React.lazy for code splitting, Suspense can coordinate loading UI for any operation that 'suspends' — meaning it throws a promise that React catches and waits on before continuing to render that part of the tree. Data-fetching libraries and frameworks (React Query in experimental modes, Relay, and frameworks built around RSC like Next.js's App Router) integrate with this mechanism so that fetching data can show a <Suspense fallback> exactly like a lazily-loaded component would.

Suspense-based data fetching is like a restaurant putting up a single 'still preparing your table' sign that automatically comes down the moment every dish for that table is ready, instead of each individual plate at the table having its own separate 'still cooking' sticker that the kitchen staff have to remember to remove one by one.

Key Concepts

1
This lets you declaratively describe loading states at the boundary level rather than inside every individual component: instead of each data-fetching component managing its own isLoading flag and conditionally rendering a spinner, you wrap a section of the tree in <Suspense fallback={<Spinner />}>, and any suspending descendant (whether it's a lazy component or a data-fetching hook designed to integrate with Suspense) is covered by that single fallback until everything inside is ready.
isLoading<Suspense fallback={<Spinner />}>
2
A notable behavior is that multiple sibling components suspending independently under the same boundary can be coordinated together (waiting for all of them) or split into separate nested boundaries for more granular, staggered loading — letting you deliberately design whether a whole section loads together or reveals piece by piece as different parts become ready.
3
Interviewers exploring Suspense's broader application beyond code splitting ask candidates to explain the throw-a-promise mechanism conceptually and to reason about where to place Suspense boundaries for a page with multiple independent data dependencies — a common follow-up is discussing the tradeoff between one large boundary (simpler, coarser 'all or nothing' loading) versus several nested boundaries (progressive, more granular reveal).