, 12 tweets, 2 min read
My Authors
Read all threads
🌀 Why Suspense matters, a short thread
Migrating jQuery rendering logic to React helped me solve UI inconsistencies. A whole class of bugs when imperative mutations to the DOM got out of sync with the underlying app state were gone. Instead of issuing commands like appendChild/removeChild, I described a consistent UI.
When I say

if (condition) {
return <A />
} else {
return <B />
}

I can be confident the UI is consistent with my state. React guarantees it. If condition is true, I'll see A, otherwise I'll see B. I won't see something broken in between. That's the whole point.
However, introducing data fetching (or any asynchronous work) breaks this consistency! If children of <A> each fetch some data (e.g. based on a route param), and that route param changes, they can be inconsistent with each other. Asynchronous data may arrive in different order.
Why is this happening? Because we’re “issuing commands” again! Instead of appendChild()/removeChild(), we now do fetch() and setState() based on that. Or something that essentially boils down to it. As soon as we add this, our UI is no longer guaranteed to be consistent.
Can we solve this somehow? For sure. I mean, people *did* write async apps for decades by now so it’s not like we don’t have solutions. They involve adding something on top (e.g. a global cache or a state machine or some kind of coordinator).
But we did lose an important property of the system. We used to have a guarantee that if we pass a prop down the tree, we're only ever going to see UI that matches this prop value. But we lost this guarantee by introducing asynchronous data fetching. We're back in jQuery days.
This is what Suspense solves. Suspense guarantees the UI you see is always consistent. Instead of "fetching and setting state", we *read* asynchronous data as if it was there. React takes care of waiting for the data to arrive, and only showing consistent results on the screen.
Of course, always waiting for *all* data to arrive would be unfortunate. It would be too slow!

if (condition) {
return <A /> // what if something inside takes too long
} else {
return <B />
}

So do we sacrifice consistency? No.
Instead of sacrificing consistency, we add a new primitive.

function A() {
<div>
<h1>Show me immediately</h1>
<Suspense fallback={<Spinner />}>
<ThisTakesTooLong />
</Suspense>
</div>
}

It lets React "cut off" slow parts in order to stay consistent.
That’s what Suspense is really all about. It’s about ensuring UI is able to always stay consistent despite some parts of it being asynchronous. Once you go all-in on this paradigm, you’ll discover interesting implications. I’ll talk about them some time later.
I should mention here that using Suspense for anything other than code splitting is still experimental 🙂 I’m sharing this to explain where we’re going and why. Not something you need to learn or use today (unless you live on the very edge or want to make your own library).
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with Dan Abramov

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!