DEV Community

Cover image for React 19 useOptimistic Hook Breakdown

React 19 useOptimistic Hook Breakdown

Danny Thompson on February 03, 2025

React is always improving and evolving with new ways to approach things and also new hooks, one of which that I have really liked using is the useO...
Collapse
 
columk1 profile image
Colum Kelly

You're not actually demonstrating anything that the hook does here. You'll see if you comment out your transition with the optimistic update nothing changes, the state still updates immediately. You could actually remove the hook entirely and state would still update optimistically the way you have written your code.

// try commenting out this part
startTransition(() => {
  addOptimisticPost(postId);
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
dthompsondev profile image
Danny Thompson • Edited

startTransition is not the hook. All startTransition API does is mark it as nonurgent allowing other calls to happen first. That is why even when it is commented out the optimistic hook is still working. That does not change the useOptimistic hook, it just changes the priority of the API calls and not using it is losing a big advantage this hook has to speed up the overall experience for the user on the page as a whole.

Since you use the useOptimistic hook, you can deprioritize the API call, allowing others to go first since the user is getting the UI feedback right away. This allows other calls to go first increasing their priority. This would not change the feedback of the UI since that is in the useOptimistic hook, NOT the API call. Hope that explains this in a clear way.

Collapse
 
columk1 profile image
Colum Kelly • Edited

I wasn't concerned with the transition. I think you're missing that the update function is in that block. When you comment it out, there's no call to the update function. At that point you're not using the useOptimistic hook anymore, but the UI is still optimistic.

Plus, as I said, if you remove the hook entirely, the behaviour of your top two optimistic posts is the same. Try replacing optimisticPosts with posts in the return of your main App component and you'll see there's no difference.

Thread Thread
 
dthompsondev profile image
Danny Thompson • Edited

Ah I understand what you are trying to point out but you missed something. Let me explain.

return (
    <div className="max-w-2xl mx-auto p-6 space-y-8 bg-blue-100">
      <h1 className="text-3xl font-bold text-blue-900 mb-8">D-witter</h1>
      <div className="space-y-6">
        {optimisticPosts.slice(0, 2).map((post) => renderPost(post, false))}
        {posts.slice(2).map((post) => renderPost(post, true))}
      </div>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

In your example you said if you swap optimisticPosts with posts, it will still render the same way. Taking it a step further, if you swap posts with optimisticPosts it will still show a delay.
Why is that?

Well, if we look further in the line to the function of renderPost() we have 2 arguements. post and a boolean value. The boolean is what we are looking for. The boolean is for isOptimistic.

<button
     onClick={() =>
         isOptimistic ? handleLike(post.id) : handleRegularLike(post.id)
     }
Enter fullscreen mode Exit fullscreen mode

The boolean is what decides is we use handleLike which uses the useOptimistic hook or if we use handleRegularLike which does not use the hook.

{optimisticPosts.slice(0, 2).map((post) => renderPost(post, false))}
{posts.slice(2).map((post) => renderPost(post, true))}
Enter fullscreen mode Exit fullscreen mode

I named optimisticPosts just for the demo so we could show the separation of the two so it would be easier to follow. It is an array method that is mapping over the array of posts. The Boolean in renderPost is what decides if we use the hook or not.

Let me know if that clears this up for you.

Thread Thread
 
columk1 profile image
Colum Kelly

The boolean is what decides is we use handleLike which uses the useOptimistic hook or if we use handleRegularLike which does not use the hook.

Yes, and my point is that your handleLike function updates optimistically without the hook. If you remove all references to this hook you still have optimistic UI. Try removing addOptimisticPost(postId), it will still be optimistic. Go further and replace optimisticPosts with posts and it will still be optimistic. The hook isn't doing anything.

Thread Thread
 
dthompsondev profile image
Danny Thompson • Edited

AH! I now see what you were saying. The hook was working but I put the timeout in the wrong spot so it wasn't actually slowing down the API call. I just slowed down the console log statement so it was always just updating the UI instantly. I moved it and now it is working. If you comment out the startTransition it will not perform optimistically now.

Collapse
 
himanshu_code profile image
Himanshu Sorathiya

You said useOptimistic hook breakdown, and guess what there was nothing related to it in this article, may be instead of covering whole video ( which is really really unnecessary ), you could've just demonstrated what is this hook used for, why it was made etc etc.

And about that hook I'm not very optimistic about it, that's not my cup of tea

Collapse
 
dthompsondev profile image
Danny Thompson • Edited

This is really good feedback. I am going to tweak this article a bit based on that to improve it. Thanks for giving it to me. You are right. I should add in some more details. I appreciate you giving it to me straight. Will work on this today. Sometimes I struggle with feeling like something is just too long and try to be direct but there should be more context on this.

Collapse
 
himanshu_code profile image
Himanshu Sorathiya

Don't fear of long articles, if it's really helpful then people won't see length of articles and they won't even notice

Collapse
 
mhmd_sahad profile image
Muhammed Sahad • Edited

Let's suppose I've two API's one for Add and other one for Get. every time when i add something i refresh list with get API. I need to use useOptimistic here. the thing is I wanna manage useOptimistic with two asyncs! How i can manage it ?