Current section: Server Actions 27 exercises
Problem

Revalidation

Loading exercise

Transcript

00:00 So we've got ourselves a problem here. We want to be able to change the names of our ships and have that represented on the left side. And the interesting thing is, you might be thinking, wait, I thought that we were sending the content to the UI. Isn't that what our back end was doing? It sends the return value, and it sends the updated content. So what's going on?

00:17 Why don't we get the latest values here? And if you were to inspect the network request, you would actually see that the latest values do show up here. So there's a disconnect here. So if you look in your root component, this is how we're getting the content. We get it from the content cache at the content key. Now we've got our promise, and we're using that promise,

00:37 and we access the root property off of it. So what gives? Well, what gives is that when we make our call to call our action, we're waiting for the response, and we totally ignore the RSC content that comes back. We just return the return value. And that's great, but we also want

00:55 to handle this RSC content. And so we can get our root from here, and then somehow we've got to get that root available in our UI down here. Well, really, all we need is the action response promise, and we need to stick that in our content cache,

01:14 our cache of all these promises. So we need to get that in the cache, and then we need to trigger a transition of our root component so that it will re-render with the latest version of our content cache. So really, you just need to have a content cache.set, and the content key, yeah, that's

01:34 going to have to come from content key will come from window.history.state.key, and of course, that's optional. And then you might want to default it, just in case somehow there's not a content key there. But yeah, then we'll set this promise there. But then again, we have to trigger a transition.

01:53 So somehow we have to say start transition, and then update the content key, like set content key to be that content key. But the trick is, while you do have a global start transition, we need this transition to be specific to our root component,

02:12 and also the set content key. That's also part of our root component. So there's some funny things going on here, because this call server has to be defined outside of the root component. Oh, what's going on? So we're going to do some JavaScript fanciness to make it so that we can simply call update content key with the content key.

02:31 The other trick, though, is that we don't want to update the content key until the content is ready to be displayed. Otherwise, we'll just instantly show the penny UI while the promise resolves, because this action response is actually streaming in over time. So it's kind of interesting.

02:50 We basically, we want to have this create from fetch that once that create from fetch itself is, or while it's still processing the RSC content, we need to update the RSC promise, so that gets updated right away.

03:09 But then we also want to wait to trigger the transition until the promise is done. And so we'll have a utility for that. OK, so there are a couple interesting things going on in this exercise step. Let's talk about, first, how are we going to call some stuff that is inside of a React component when we're outside of it.

03:28 It's actually pretty simple. Here, we're going to define a function, and then inside of a use effect in our component, we're going to reassign that function to do something else. So then, at any other time, you can call this increment function even outside of React, and it will trigger the set count.

03:44 This is not totally advisable for regular components because you often have multiple instances of regular components. But in our case, we're doing this for the root component. We're only going to have one, and so having a global version of some internal functions is going to be fine. OK, so the other thing we need to manage

04:04 is updating the content key, as we discussed. But that needs to happen only after this action response has totally resolved, and we want to update the content cache before it resolves. So we need to have some way to say this, and then after it resolves, we could add an await.

04:22 But we also need to return this sooner. It is kind of interesting how all this is going to work out. So what we do instead is we're going to have this utility for you called onStreamFinished, where we pass our promise, and we pass a callback that we want called when that promise is finished.

04:41 All this is going to do is make a copy of the response, convert it to text, and then add a then to that, so that once all of the response is finished streaming, then we can call this promise. It's kind of funny, but it works, and it works well. And so then you can pass your fetch promise to onStreamFinished, and that's when you

05:00 get to update the content key. And then from there, you can take the action response promise and do all the rest of stuff with it. And this update content key is going to be our fancy function that we can call to start a transition within our root component and update the state of our component to the content key.

05:18 Now, I'll add one last thing, and it is possible that, and actually kind of likely, that the content key will be the same. And so this state change actually doesn't trigger any real changes. However, our update content key will also be starting a transition, and that's

05:35 what's going to trigger our re-render of our components so that we get the latest version of our content for the particular content key. So a bunch of refactorings, moving some things around, doing some funny JavaScript things. But this is why you use frameworks, because they do all this stuff for you. But you get to do it now so that you

05:54 can understand what's going on a little bit better. And one last thing I'll call out is that this is all implementation detail specific to our implementation. Other implementations of RSCs might do other things, and that's totally fine. But yeah, this is what we're going to be doing, and it works. So let's get into it.