Skip to content
C Codeloom
React

React SuspenseList Tutorial

Coordinate multiple Suspense boundaries with SuspenseList to control reveal order and loading states, reducing layout shift and chaos during streamed data fetching.

·4 min read · By Codeloom
Advanced 10 min read

What you'll learn

  • What SuspenseList coordinates
  • revealOrder and tail props
  • How it pairs with streaming
  • Where it fits in real apps
  • Caveats and current status

Prerequisites

  • Familiar with React Suspense

Suspense lets a component pause rendering while it waits for data. SuspenseList is the conductor that decides how a group of suspending children reveal themselves. Used well, it turns chaotic loading flicker into smooth, predictable UI.

What and Why

When you have one Suspense boundary, React shows the fallback until the child resolves, then swaps it in. When you have several side by side, they each resolve whenever their data lands, which can create a jittery cascade. The first card appears, layout shifts, the third card appears, more shift, and so on.

SuspenseList sits above multiple Suspense boundaries and coordinates them. You tell it the reveal order you want and how to handle still-pending siblings. It is part of React’s concurrent rendering story and pairs naturally with streaming server components.

The benefit is calm UI. Users see a predictable order of content even when network timings are random.

Mental Model

Imagine three lanes at an airport security checkpoint. Without coordination, travelers leave in whatever order they finish. With a coordinator at the exit, they leave in arrival order or wait until a batch is ready. SuspenseList is that coordinator for your Suspense boundaries.

Two props drive the behavior. revealOrder can be forwards, backwards, or together. tail can be collapsed or hidden to control how many pending fallbacks show at once.

Hands-on Example

Picture a feed with three cards that each fetch independently.

forwards:  [A]      [A][B]    [A][B][C]
backwards: [C]      [B][C]    [A][B][C]
together:  ...      ...       [A][B][C]
revealOrder controls how siblings appear
import { Suspense, SuspenseList } from 'react';

function Feed() {
  return (
    <SuspenseList revealOrder="forwards" tail="collapsed">
      <Suspense fallback={<Skeleton />}>
        <Card id="a" />
      </Suspense>
      <Suspense fallback={<Skeleton />}>
        <Card id="b" />
      </Suspense>
      <Suspense fallback={<Skeleton />}>
        <Card id="c" />
      </Suspense>
    </SuspenseList>
  );
}

With forwards, card A always reveals first even if C finishes first. With tail="collapsed", only one skeleton is shown at a time for the next pending item, instead of a long stack of skeletons.

Switching to together makes all three wait until every child is ready, then reveal as a single block. This is useful for tables where partial rendering looks worse than a single delayed swap.

tail="hidden" shows no fallback for siblings that come after the next pending one, useful for infinite lists where the count is dynamic.

Common Pitfalls

The biggest one is API status. SuspenseList shipped as experimental and has been on a long road. Check your React version and docs before relying on it in production. Some bundlers and frameworks expose it differently or not at all.

Another trap is reaching for SuspenseList when a single Suspense boundary would do. If the cards share a single query, wrap them all in one Suspense and skip the coordination cost.

Mixing SuspenseList with non-suspending children gives surprising results. The list only orchestrates direct Suspense children. Place anything else outside or inside its own Suspense.

Finally, SuspenseList does not change when network requests start. They still kick off in parallel. It only changes when the UI is allowed to commit.

Best Practices

Use forwards for top-down content like feeds or article lists where reading order matches reveal order. Use backwards for chat-style UIs where newest items appear at the bottom and you want the bottom to settle first.

Use together for grids and tables where partial reveals look broken. Combine with tail="collapsed" to keep the loading state tidy.

Always pair with meaningful fallbacks. Skeletons matched to the final layout prevent the layout shift that SuspenseList is helping you avoid. A spinner that pops into a card-shaped slot defeats the goal.

Test with throttled networks. The behavior is invisible on a fast connection, so simulate slow conditions to verify the reveal feels right.

Wrap-up

SuspenseList is a small API with a big effect on perceived quality. It lets you orchestrate Suspense boundaries so loading states feel intentional. Check its current status in your React version, and when available, use it to turn chaotic streams into a calm reveal.