Transcript
00:00 So, the first thing we're going to do is bring in our content cache. You can feel free to dive in there to get a sense for how this is all implemented. Not related to RSEs, but it is still pretty cool, so feel free to dive in. But this is going to hold all of our content promises, so that when we re-render, we'll have those available in that cache instantly. Okay, great.
00:19 So, just to get us all started, we need to have an initial content key. So, we're going to get that from our history state. So, our initial content key is going to be window.history.stateKey. Now, it's possible that there's nothing in there.
00:36 So, if there is no initial content key, then we'll want to update the state to be a new generated key. So, we're going to need actually our initial content key to be reassigned to this generated key here. So, let's do a let right here. There we go.
00:56 And our initial content key is going to be that generated key. There we go. And I'm going to comment this out for a second, just so we can observe. If we go to window.history.state, our state is null there. And yeah, now we're blowing up.
01:13 But the important thing here is that our state is null if we haven't already set it, and that's why we say replace state right here, so that we update that state to be replaced by a state that includes the content key. Now, another thing you might consider is, like,
01:30 maybe there are other elements of state that you want to include in your replacement here, but this is as far as we're going to go there. Okay, great. So, now we're going to add the key to our cache. So, we'll say contentCache.set.
01:46 Our initial content key is going to be this initial content promise. And that takes care of this. Now, we are getting an error right here, reading state right here on window.history. So, let's fix that. History.
02:03 I know, like, there were probably many of you watching right now saying, Kent, you forgot the Y. So, there we go. And, you know, that's almost a metaphor for life. Did you forget the Y? Don't forget the Y. Okay, great.
02:16 So, now we've got our content key initialized properly, defaults to some new generated key, and then we replace our current location history state to include that content key, and then we update our cache to include the initial content promise.
02:33 If we take a look now at our window history state, we will see it's an object that has a generated key. Super. So, now we need to update our root so that it's retrieving the promise from the cache rather than managing the promise itself.
02:48 And so we're going to get our content cache from our use content cache hook, and this is going to be our map that we can set and whatever mappy things we want to do. We're going to change our state from content promise to content key, and this will be our initial content key.
03:07 And then we get our content promise now from, no, we don't need to use it, from our content cache, get content key. Okay, super. Now, everything that was using the content promise before is going to work just as well. In fact, if we save this now, everything should work as it was before.
03:25 No changes there. So, and of course, now this is calling set content promise. That's not a thing anymore. So, we want to set the content key. So, let's update that to set the content key, and we're going to have a history key that we're going to be using here.
03:40 So, let's create that history key from window history state key, or we will fall back to a new generated key. This is an unlikely scenario. It probably should never happen, but things that you say should never happen absolutely will happen at scale, so you do want to handle that situation.
03:58 In a TypeScript code base, this would say, hey, this could actually be undefined. Do you want to handle that? So, we're going to handle that here, and now we're setting our history key. So, the trick now is we need to get this next content promise inside our content cache.
04:14 So, we'll say content cache dot set at that history key, the next content promise. However, this isn't really a cache if we're not actually leveraging the cache functionality,
04:26 and so what we're going to do is we'll say if the content cache does not have an entry for that history key, then we will go and update all the things.
04:38 Otherwise, we'll just use that cache value already, which should already be in our cache, so we don't have to refetch everything if it's been cached. Okay, great. And then down here, rather than setting the content promise, we also need to set the content key to our new content key,
04:57 which we're going to get by creating a new content key with generate key, and then we'll update that in our content cache. And with that, the last thing we need to do is make it so that every step in our history has the key associated to it,
05:16 so as we do the pop state thing, we can access that. So that is coming from our history state right here, and that is being set right here in this object. So we can say our key is the new content key for both of these. Key, new content key. And then we can get rid of both of those, save this,
05:34 and now we shouldn't have any trouble with our state as we're navigating around. So here we go, forward, forward, and then go back, back, instant navigation, and there we go. That looks awesome.
05:51 It's doing what it should. Awesome. So let's just quickly review what we did here. Most of this was just refactoring stuff so that we can put things in a cache. We have it external to React because we want to do this on the initial render as well,
06:08 and so we have our content cache where we set the initial key and the initial promise, and then we have our content cache accessed via use content cache. This is coming from a USYNC external store because our cache is a map that's an external store. We're going to retrieve our content promise from the content key, which is what we're managing in state now.
06:27 It's no longer the promise itself. We're just managing the key, and then we access the content promise from that cache. And then whenever we want to access that in our pop state event handler, we're going to say, hey, if there already is something in the cache, then we don't need to bother.
06:43 It's only when there isn't something in the cache that we need to make a request and all of that stuff for updated content. And in either case, we're going to update the content key so that the latest UI can be rendered properly.
06:57 And, yeah, then in our navigate function, we're going to manage keeping that key up to date and always setting the content key in the cache so that when we eventually get around to this line, we have that key or we have that content in our cache and we can use that promise,
07:16 which in the future, as we're going backward and forward in state, that's already been resolved and it already has all of its state and everything. So there you go. Now we don't have suspense boundaries being shown and we get our UI, our pending UI and stuff,
07:33 working for our actual user interactions. But for forward and backward, we've got it in the cache. It renders instantly.