4 Best Ways to Use React’s Suspense Component

Nivetha Krishnan
Bits and Pieces
Published in
5 min readMar 2, 2023

--

<Suspense> lets you display a fallback until its children have finished loading.

Suspense is a new feature that lets your component “wait” for something before it can render. Some of the use cases where it is used are data fetching and waiting for images, scripts, and other asynchronous work to load.

Suspense does not detect when the data is fetched inside an Effect or Event handler. The <Suspense>component will be activated only by the Suspense-enabled data source.

Props for Suspense Component

  1. children: They are the actual UI you intend to render. The Suspense boundary will switch to render fallback when the children takes too long to render.
  2. fallback: It is a lightweight placeholder view such as a loading spinner, An alternate UI to render in the place of the actual UI if it has not finished loading.

Suspense will automatically switch to fallback when children suspends, and back to children the data is ready. If fallback suspends while rendering, it will activate the closest parent Suspense boundary.

1. Display a fallback while the content is loading

React will display your loading fallback until all the code and data needed by the children has been loaded.

You can wrap any part of the application within the Suspense boundary:

<Suspense fallback={<Loading />}>
<Albums />
</Suspense>
function Loading() {
return <h2>🌀 Loading...</h2>;
}

In the example above, the Albums component suspends while fetching the list of albums. Until it's ready to render, React switches the closest Suspense boundary above to show the fallback(Loading component). Then when the data loads, React hides the Loading fallback and renders the Albums component with data.

2. Revealing content together at once

By default, the whole tree inside the Suspense boundary is treated as a single unit.

<Suspense fallback={<Loading />}>
<Panel />
<List>
<Albums />
</List>
</Suspense>

For example, even if only one of these components suspends wait for some data, all of them together will be replaced by the loading spinner. After all of them are ready to be displayed, they will all appear together at once.

Components that load does not have to be direct children of the Suspense boundary.

<Suspense fallback={<Loading />}>
<Details artistId={artist.id} />
</Suspense>
function Details({ artistId }) {
return (
<>
<Panel artistId={artistId} />
<List>
<Albums artistId={artistId} />
</List>
</>
);
}

For example, you can move Panel and Albums into a new Details component, This doesn’t change behavior. Because Panel and Albums share the same closest parent Suspense boundary.

3. Revealing nested content as it loads

When a component suspends, the closest parent Suspense component shows the fallback. This lets you nest multiple suspense components to create a loading sequence.

<Suspense fallback={<PanelSpinner />}>
<Panel />
<Suspense fallback={<AlbumSpinner />}>
<List>
<Albums />
</List>
</Suspense>

The loading sequence will be:

  1. If Panel hasn’t loaded yet, <PanelSpinner> is shown in place of the entire content. Once loading is done Panel component is displayed
  2. If Albums hasn’t loaded yet, <AlbumSpinner> is shown in place of Albums and its parent. Once loading is done Albums the component is displayed.

Each Suspense boundary’s fallback will be filled in as the next level of content becomes available. Suspense boundaries let you coordinate which parts of UI should always “pop in” together at the same time, and which part should progressively reveal more content in the sequence of the loading state. You can add, move or delete suspense boundaries in any place in the tree without affecting the rest of your app’s behavior.

4. Providing a fallback for server errors and server-only content

If you use any server rendering APIs, React will use <Suspense> boundaries to handle errors on the server. If a component throws an error on the server, React will not abort the react render. Instead, it will find the closest <Suspense> component above it and include its fallback.

On the client, React will attempt to render the same component again. If it error on the client too, React will throw an error and display the closest error boundary.

<Suspense fallback={<Loading />}>
<ErrorPage />
</Suspense>
function ErrorPage() {
if (typeof window === 'undefined') {
throw Error('Chat should only render on the client.');
}
// ...
}

To some components from rendering on the server, throw an error from them in the server environment and then wrap them in a <Suspense> boundary to replace their HTML with fallbacks.

The server HTML will include the loading indicator. It will be replaced by the <ErrorPage> component on the client.

Conclusion

While using <Suspense> component, React will wait until enough data has been loaded to prevent an unwanted fallback from appearing. This will avoid hiding existing content.

However, any newly rendered <Suspense> boundaries will still immediately display fallbacks to avoid blocking the UI and let the user see the content as it becomes available.

💡 Note: If you’re building a large application with multiple teams or projects, you may find it challenging to manage <Suspense> components across all your projects. This is where an open-source toolchain like Bit can help. Bit allows you to isolate, share, and reuse components across different projects, making it easier to manage updates, ensure consistency, and improves team collaboration. Learn more here, here, and here.

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--