Transcript
00:00 Optimistic UI, all right. This is something that I have, I've worked on optimistic UIs for like a decade now. I've built optimistic UI in every framework that I've used, and I'll tell you what, I'm optimistic about the future of optimistic UI
00:17 because it's become a lot easier than it used to be. Remix is by far the best at this. I'm wearing a Remix shirt right now actually, and I am super fan of what Remix has done. And React has a use optimistic hook that I'm optimistic about as well. So what is optimistic UI?
00:37 Let's imagine that you're on x.com and you want to go favorite a post. And so when you click on it, the little heart turns red right away. But what if you're on a slow network or something? It's still going to turn red right away because they are implementing optimistic UI. 99.999% of the time,
00:56 when you favorite a post like this, it works. And so they don't want you to have to wait for the request to be made and to come back and validate all of that stuff. They're just like, it's probably going to work. Let's just show it red right away. And so implementing that is actually not all that challenging. The really challenging part is what happens if it doesn't work?
01:14 Maybe the post was deleted and you are looking at a deleted post and you try to like a deleted post, that's not going to work. And so you've got to roll back. So that is what makes optimistic UI kind of complicated, but React's use optimistic hook actually makes it pretty straightforward.
01:33 So here's an example of how you implement optimistic UI with React. So we have this to do, and here we have a use optimistic. This is actually pretty similar to the use state hook. It's accepting a value here. It's actually not the initial value.
01:51 This is the fallback value when we're no longer being optimistic. So this actually will matter in future renders. We get the is complete and set is complete. And then we have our form with our input and the checked state is based on whether it is complete. And so whenever this form action is submitted,
02:09 I suppose this form is a little incomplete itself because this action won't be called until it's submitted and we don't have a submit button or anything. But just imagine with me, once this action gets called because the form submitted, we're going to have this async action be called.
02:26 Now, actions are called, form actions are called within a transition. So that use transition hook and is pending, all of that stuff, these actions are called within a transition. So if there's any asynchrony going on, any suspending, anything like that, then the old UI is gonna be held around
02:44 until the new UI can be updated and all of that. So that means that any state changes that you make inside of this action are not going to be revealed to the user until the action is all finished. And so this is why you can't just use state because if you try to update the state,
03:03 then React is just gonna assume that that state update is part of the transition. And it's gonna say, okay, great, I'll keep that in mind. And I'm gonna keep on waiting for this transition to be done. So this is why we have use optimistic. You might think of use optimistic as like use transition state. So it's state that can be updated during a transition.
03:23 And so here we're saying set is complete to the opposite. And now is complete, this will re-render the component. We get is complete so that the user can instantly see, oh, okay, they do listen to me. It is checked, all of that, so on and so forth. And then once this is all finished,
03:39 then this use optimistic state to do will get re-rendered and because we're no longer in the transition anymore, the state that we set before just disappears. And we go back to whatever the to do dot is complete value is and so we fall back.
03:58 And so that means if there's an error of some kind, the transition will be done and we'll fall back to the actual value of the data. And when it successfully completes, as long as the data is up to date, then it will fall back to whatever that data is and it will be correct. And so, yeah, this is just a mechanism
04:16 for updating state during a transition. And typically you're gonna be using this to implement optimistic UI, but you could also use this if you had like multi-stage things, so like create the order, then send to the shipment, then whatever. Multiple stages of what you're doing, then you can have like, here's what I'm doing right now
04:35 and here's what I'm doing now and here's what I'm doing now. And you could update the message that you're showing to the user, which we're gonna be doing in this exercise. The other relevant piece to this that can also be used to implement some optimistic UI or at least some pending UI, but yeah, some optimistic UI is use form status.
04:54 So this can be used within the context of a form. So you might have something like this and what that will allow is you kind of think of the form as being a context provider and this use form status is like a context consumer.
05:11 So it's gonna look to its nearest form parent and it's going to keep track of the status of that form. So if it's pending and if it is pending, it's gonna have the data that is being submitted, all of that stuff. And so that is how you can use form status
05:30 to implement some pending UI, but then because it also has the data, you can do some optimistic UI in here as well. The one caveat being that this needs to be rendered as a child of the form. You can't use form status inside of the to-do because the form is not the parent of the to-do,
05:48 the to-do is the parent of the form. And so it does have to be a child, pretty useful for like a reusable component library or something like that. You make a submit button that has like a little cool spinner or something like that. And then you can use it in any form and it'll get its form status just automatically. Pretty cool.
06:07 So with those bits of information, we can get into our exercise. Let's get into it.