Understanding the Suspense API in React 18

What is the new ReactJS Suspense API and when should you use it?

Fernando Doglio
Bits and Pieces
Published in
5 min readJun 13, 2022

--

Photo by Mike van den Bos on Unsplash

When components start to get big and you have many of them on the same page, you might want to start optimizing the way and the moment they get downloaded into your client’s browser.

For that React provides you with the lazy method, which allows you to mark components as “lazy”. This in turn means they get downloaded the first time they’re used and not before.

This is a fantastic way to decrease the “time to first pixel” and other metrics that measure the amount of time your app takes to render for the first time and the time it takes to be “ready” for interactions.

But when you use this optimization, you run into a bit of a problem: what happens if the component takes too long to download? Especially in slow connection environments, this can be a problem.

What should your app show? How can you let your user know that something is happening even though they can’t see it?

That’s where the Suspense API comes into play, so let’s take a look at it!

What is the Suspense API?

The Suspense API works in conjunction with “lazy” components to let your users know that they’re loading something in the background, while they’re loading it.

It does so by providing an alternative visualization (a different component) while the slow, lazy component is being downloaded for the first time.

The premise here is that this alternative component is a low smaller and most likely can be reused in many different places. That way the trade-off makes sense.

Think about Suspense as a way to show the “loading…” message, the spinning wheel or even the type of skeleton component while the actual one is being processed and downloaded.

Using requires you to simply wrap your lazy components with the Suspense one while specifying the fallback property. Like this:

As you can see, both the Text and Buttons components are lazy, and loading either of them will require a request to the server. The “Toggle” link simply alternates between both of them.

Now the interesting bit here is that the Suspense component doesn’t have to directly wrap the lazy components. They can be many levels down the tree, and the fallback would be shown anyway. So you don’t have to worry about wrapping every single component with it, you can wrap a whole section of your component tree and have them all use the same fallback.

Look at the above GIF, it starts off with a white screen because it’s slowly (notice the Slow 3G setting on the Network tab) downloading the initial page. Immediately after, you’ll see the “Waiting for content…” message, that’s the Waiting fallback.

Then it gets replaced by a text message, that’s the Text component that was loaded. We’re seeing here the Suspense API in action.

Then when I click on the “Toggle” link, you’ll see the “Waiting for content…” message again for a few seconds, while the browser is downloading the Buttons component for the first time.

After this, the switch between components is immediate, because they’ve already loaded and the Suspense API is no longer needed.

If you want to know more about Suspense, I would recommend reading the RFC here, since it provides you with all the context you need to understand the feature.

What about the transition API?

As part of React 18, there was an addition to the Suspense API, which allows you to transition between components in a way that might be more user-friendly in some situations.

If you go back to my example, you’ll notice that every time I click on the “toggle” link, the UI changes to either show the new component or show the “Waiting for content…” message.

Depending on the type of component you’re loading, this might be too big of a change for your users, so instead, you might want to keep your UI still visible and let your users interact with it, while at the same time, React loads the new component in the background. Only once the new component is ready, it will replace the old one with it.

You can do this now, in React 18, with the transition API, like so:

This is the exact same code, but now when we click on the “Toggle” link, we call startTransition which in turn sets the correct tab to show. This tells React to replace the component only once its loading is complete.

And because the lack of a loading indicator might be a bit confusing to the user, we get the isLoading boolean that gets returned from the useTransition hook. This boolean value can be used to indicate that something happening without completely destroying the user’s experience. In my case, I’m setting the opacity of the “old” component to “0.1” while the “new” one loads.

Now if you were to run this example, you’ll see that the fallback is used for the first time, and then the transition gets called whenever you manually change tabs. That provides a heck of a better experience to your users and still keeps things as optimized as possible.

The Suspense API is not complicated, nor does it add too much code to your existing project. But it’s also true that you might not need it if your application is not complex enough.

To determine whether you should or shouldn’t add it, the first question you should ask is: how many components am I rendering on each page and how many components am I loading to do it? Profile your app’s performance and determine if this number is actually causing some of the initial loading time issues. If so, then yes, start code-splitting and introduce the Suspense API.

Otherwise, you can keep going without it.

Bit: Feel the power of component-driven dev

Say hey to Bit. It’s the #1 tool for component-driven app development.

With Bit, you can create any part of your app as a “component” that’s composable and reusable. You and your team can share a toolbox of components to build more apps faster and consistently together.

  • Create and compose “app building blocks”: UI elements, full features, pages, applications, serverless, or micro-services. With any JS stack.
  • Easily share, and reuse components as a team.
  • Quickly update components across projects.
  • Make hard things simple: Monorepos, design systems & micro-frontends.

Try Bit open-source and free→

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/