Understanding useOptimistic
under the hood.
#33790
Replies: 2 comments 1 reply
-
How useOptimistic Really Works The JavaScript Illusion The Clever Guess Why This Matters |
Beta Was this translation helpful? Give feedback.
-
Hi Priyansh! I love how deeply you’re thinking about this — you’re already connecting a lot of the right dots. Let me try to explain it in a way that might feel a bit more natural and grounded.
But under the hood, it’s juggling a bit of magic. Here’s why it’s needed…
So React has no built-in way to know: "Which startTransition() did this async thing belong to?" "Is this async result still relevant, or has the user already moved on?"
A transition (like submitting a form or clicking to load something) gets its own lane. React uses this to remember, “Hey, this optimistic UI belongs to that async action.” So even after the async call finishes and JS has forgotten what happened, React can still check: is this lane still active?
You call startTransition() and kick off your form submit. React creates a lane for that transition and applies your optimistic UI change. Your async function hits await, and JS wipes the call stack. Eventually, your async function finishes. Now React asks: “Is the lane for this transition still pending?” “Has a newer transition already happened?” If yes → it discards your update (it’s stale). :) Quick Analogy You (user) place an order (transition). The waiter (React) shows you a fake dish instantly (optimistic update) to keep you happy. Meanwhile, the chef (async function) is cooking the real thing. But if you suddenly change your order (newer transition), the old dish is tossed out when it’s done — no point in serving something you no longer want. :( Why This Matters That’s why things like unique IDs for transitions or careful state design help React keep track of what’s what. Anyway — hope this gives some more clarity! The fact that you're thinking in terms of call stacks, browser execution, and reconcilers tells me you're right on the path to understanding how React really works under the hood. Keep digging — you’re close! Let me know if you want to dive depper... 😊 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm slightly confused as to how the useOptimistic hook works under the hood.
From Deep Dives I have looked up online specifically this one I slightly understand the concept but since I am still beginning understanding the deepdives into frameworks like these, I really wanted to know if I could get a solid understanding and verification of my understanding as to how useOptimistic works under the hood. The thing that really piqued my interest was the comment in ReactFiberHook in the react-reconciler was that having multiple asynchronous actions like form actions cannot be distinguished because in execution of javascript generally or the browser (i am unsure if they have a difference) the Call Stack Context of Function destroys / completely unwinds a call after an await. So if I am not misunderstanding, this implies that as soon as we hit an await, the entire call stack upto that request gets wiped so I think the "transition", or event resolution we were looking for doesn;t exist anymore and goes back to null, (I might need help understanding this)and the startTransition in the call stack gets destroyed when the promise resolves.
Another few terms I want to clarify is that:
A lane is basically React's way of batching multiple updates. A transition is one of these lanes, which holds transitions, which are not urgent to react if i am not wrong while SyncLanes are higher priority which are used in dispatching optimistic updates. Currently React has no way of knowing which pending action should be the one that should be resolved because the callStack doesn't let us see which transition gets resolved by which Promise Resolution/Async Return, and React's way of handling this is seeing if the transition lane / if there is a pending async request (assuming that the same function holds the same events for now) of the current event we performed and stored in our unique transition lane. (I am assuming each unique type of event goes to it sown unique type of lane). And we trigger the Actual resolved promise once we see that the pending request doesnt exist?
I could be completely wrong in my understanding and would love to hear a good analogy or explanation of how this works under the hood because it is really interesting!!!
Beta Was this translation helpful? Give feedback.
All reactions