`useOptimistic` to Make Your App Feel Instant
Make your React apps feel instant with the new useOptimistic hook from React 19. Improve UX by updating UI immediately while async actions complete.

Let's analyze this React tree structure:
Let's assume that App
renders the ShipSearch
and ShipDetails
components,
passing props as needed.
ShipSearch
is a server component which takes a search
and uses that to
perform a database query:
The ShipDetails
component is also a server component which takes a shipId
and uses that to perform a database query:
Because these are sibling components, both queries will run at the same time.
That's all fine. But let's say the App
component needs to resolve a logged in
user:
Uh oh, now we have a waterfall:
The issue here is now App
is waiting for getLoggedInUser
to resolve before
it can render anything. This means both searchShips
and getShip
won't be
executed until after getLoggedInUser
resolves, even though those don't
directly depend on the user.
This is a problem generally for React Suspense as well and I dive deep into that in the React Suspense workshop exercise 6.
There are a few ways to think about this problem:
Maybe it's not a problem if getLoggedInUser
is fast 🤷♂️ But that's not always a
sure thing, and even if it's fast today doesn't mean someone won't add something
else that will be slow tomorrow. Still, it's always good to think about how bad
ignoring the problem would actually be since there could be bigger fish to fry.
Alternatively, we can lift searchShips
and getShip
into App
and pass the
results down to ShipSearch
and ShipDetails
. Then we could use Promise.all
to make sure they run concurrently. But passing props can get annoying pretty
fast. We can use a library like
@epic-web/cachified
to dedupe the
queries and then App
simply kicks off the query earlier which would at least
be better.
Unfortunately, another issue though is this can get unweildy pretty fast,
especially if there's logic around which queries should run based on other
props. You'd have to move all that logic until your entire app lives in App
😱.
The next solution I can come up with is to use or build a compiler which can find all queries and preload them automatically. This is what Relay is. There are quite a few things I don't like about this approach though:
So I guess what I'm saying is I don't like any of these solutions. But I'd like to reframe the problem with more context.
Let's say we live in a world where we don't have RSCs or Suspense. You're just building an app with components that fetch data and render stuff.
In that world you've got three options:
Sound familiar? It's exactly the same problem we've always had with components and data. There's always been this tension between colocating and passing down data (prop drilling).
One of the nice things about Remix is that it gives you a fourth option:
This allows Remix to load data as soon as the request comes in regardless of whether the component has rendered.
This is what I've been doing for years and it's been awesome.
This blog post isn't really about why I think RSCs are awesome. You can read React Server Components: The Future of UI for that. Just know that composition at route boundaries is not as good as composition at component boundaries and I want React-level composition badly.
What I want to do is show how RSCs fit into the same tension between colocating and prop drilling that we've always had with components and data. There's no new problems here.
But what I find interesting is how a server-side waterfall is probably better than a client-side waterfall primarily because you get to control the network. The connection between your server rendering server and your database is probably stronger, faster, more reliable, and closer. Or maybe it's not, but the point is you are in control there and can make improvements to that if it's important to you. You also have more fine-grained control over caching (requests from separate clients can share a cache for common data).
When you have a client-side waterfall, you're dealing with the user's device and their network connection which may be great or may be terrible but you definitely have no control over.
So shifting this problem from the client to the server sounds like a net gain for many scenarios.
The "waterfall" problem of RSCs is not a new problem. It's the same tension between colocating and prop drilling that we've always had with components and data. Maybe there's a new solution we can look forward to in the future. I welcome ideas (preferrably something that doesn't require a special compiler)! Until then, I'm actually pretty happy with just making things fast enough that the problem isn't a problem.
Delivered straight to your inbox.
Make your React apps feel instant with the new useOptimistic hook from React 19. Improve UX by updating UI immediately while async actions complete.
React Server Components are going to improve the way we build web applications in a huge way... Once we nail the abstractions...
Some common mistakes I see people make with useEffect and how to avoid them.
Epic React is your learning spotlight so you can ship harder, better, faster, stronger.