chan.dev / posts

Use Suspense Today

Believe it or not, you’ve had access to Suspense for a year.

Yes, there is more suspense to come.
Yes, that “more” isn’t totally ready.
No, that doesn’t mean you can’t use Suspense today.

React.lazy and Suspense sitting in a tree

React v16.6 introduced React.lazy
A way to code-split in client-rendered applications by components.

import React from 'react'
const LazyLoadedComponent = React.lazy(
() => import('./SomeComponent')
)
function MyApp() {
return (
<React.Suspense fallback={<div>Waiting...</div>}>
<LazyLoadedComponent />
</React.Suspense>
)
}

lazy depends on Suspense to present a fallback while the lazily-loaded component is fetched.

In that way, Suspense acts as a boundary for asynchronous data.
If a promise inside a Suspense boundary is pending, The fallback is presented. Once resolved, children are presented.

But Suspense needs a translator

Suspense can’t magically know all the promises it’s children may or may not have.

That’s where lazy comes in.
It acts as a translator.

lazy wraps a dynamic import and communicates Pending and Resolved states to the nearest Suspense component boundary. (code here). Suspense will resolve fallback or children accordingly.

The future™️

As we move into a Suspense future, you’ll see this pattern more often:
A Suspense boundary (with fallback)
And data, wrapped in “translator” (React.lazy, ReactCache.createResource, etc).

What’s Next? Errors

Not all promises resolve.
Some are Rejected.
I’ll show you how to handle that state next time.