State Management in Pure React, v2 Persisting State & useRef
This course has been updated! We now recommend you take the React Performance course.
Transcript from the "Persisting State & useRef" Lesson
>> So this is components that completed, this is very similar to what we had, originally I did. We had a spoiler alert with a question, but I did show the syntax where you can skip the constructors in this case. So it doesn't always be as much binding but we talked about the fact that this isn't supported out of the box.
[00:00:20] You do need a battle plugin which happens to be installed in create react app but not not necessarily out of the box in a custom setup. We set component DidUpdate. And we're gonna give ourselves a little bit of a timer here we'll say set timeout. This is the simulate.
[00:00:37] So we can tell from the click to what the actual component did update happen. So we'll say set timeout will go to function and we'll say console log. And we'll say count Is this.state.count. And we'll just have it wait three seconds, that's enough for me to slam on the increment button and see what happens.
[00:01:08] All right. Cool, so I'll hit increment a bunch of times. You can see that 7 times we logged to the console the number 7, right? Which meant we are, mutating is not the right word, but we're still referencing the same this.state.value. Right, like we call this .state, which is still stored on that object.
[00:01:35] So when all of those three second delays caught up,it's like, all right, what is this .state? What seven, right? Which makes a certain amount of sense, mostly because because we just saw it happen, right. Like, I think we did a guessing game, we probably would've said either one, two, three, four, five, six, seven or seven, we might've been 50/50.
[00:01:51] But here we can see, we're staring with the evidence in our face. That when all those sub timeouts caught up, they tried to read this .state, well we hit it seven times, it is now seven. So what I'm gonna do, is I'm gonna switch back. So we can see the difference.
[00:02:17] Local storage. That's fun. Switching branches is fun. Let's go ahead and just turn this into a useState for now And I remove these other effects. All right, so what happens if we do the same thing here now? We'll give it a set timeout. 3,000 and we'll say console log.
[00:02:59] Cool. Effectively the same code instead of component did update, we now have and this is all up on the account prop. Component update was gonna run all the time. We might wanna add conditionals if we have had multiple props, so on and so forth. This is only listening for the variable count property rather state.
[00:03:40] So when all of those new timers caught up they were like shat is this state was this the state was this state, right? In the case of the function components, it is a unique call of the function every single time. So the first time count was zero and this was the one that's incrementing by five, but if I did decrement, a bunch of times, you'll see it by one.
[00:04:01] So it is a unique call to every function, right? Which means you're getting a copy of the state and the props every single time, you're not referencing a class property on an object. And so this is again, one of those subtle differences. You're like, I'm gonna refactor all the things to hooks and then all of a sudden like it starts going very poorly for you.
[00:04:20] Right as these kind of very subtle differences in between the two and like how they work, which is interesting, right? Well, what would we do in the event that we actually wanted to persist some amount of state? Right? We wanted to know, like, we had a bunch of ways before of telling what the state was, what will be next time the class based components because it's unique every time.
[00:04:43] We don't have a great way. I mean, we do but like in our current conversation, we don't have a really great way of persisting any data between renders. All right, I want to know what it was last time or something along those lines where I want to store a value in between each invocation of this function.
[00:05:00] We need a way of doing that. Like there are subtle use cases, right? Do you wanna go back to the previous state like a very simple undo? Do you wanna find out if the number is now higher or lower than it was before? Right, well, in order to tell the number was higher, lower than was before, you're gonna need to know what it was before and what it is now.
[00:05:21] Right? And could you start storing multiple things in stage and trying to shuffle them around? Sure. And in a simple counter application that might even work, right, but you can see a world where that doesn't work super well. There is a way to do it. And it's actually using a another hook that's used for a second thing that we'll talk about in a second.
[00:05:41] You might have seen before, like, Rex has this idea of refs. Right? And a ref is usually we give it to a DOM node that we want to be able to target and focus. Well, that's going to theoretically persist. You might want that. But, it also gives it is an object that kind of stays there.
[00:05:58] And, you can actually reference it and will stay it'll be the same object over time. So for instance, if I did this. I'm gonna just clean up just a little bit here, let's make this back to a set count of, C + 1, I wanna get rid of some of these other ones up here for a second, it's what I use when I'm tired of the ES on console logs.
[00:06:26] All right, now we're incrementing by one the same way we were before. Now, we could theoretically go ahead and get a, It's gonna be this React.useRef, right? Now Ref, it's gonna give an object which effectively looks like this. It has this current property on it, right? And the reason for that is that way I can persist the object cuz we said before primitives are passed by value.
[00:07:01] Objects are passed by reference. So this way we can still keep referencing the same object. So we can set this, and if we can set just once it will be the same every time it will be persisted right, it'll be the same dominoed will be the same value, so on and so forth.
[00:07:14] So what we could do is we could say something along the lines of we wanna update it. We will update it to the current count. Now this is silly, this isn't gonna do anything for us yet, because we're gonna say all right, we got a new count I'm gonna say that the thing that persist is that.
[00:07:35] But it means it in this space here. Before I use that ref, it is the previous value. Right, because we're setting it every time. But until we set it, we have access to what it was. So I could say something along the lines of. If count ref current is less than count, we'll make a message.
[00:08:05] The message is that it was previously higher. Otherwise, it's created in the account we'll say is previously lower. Right? Cuz this will now persist between every render. We're reassigning it otherwise it would just be null the first time, so on and so forth. And so what we'll just do quickly here as we say we'll put it, Right It's now higher, it's now higher, it's now lower, it's now lower.
[00:08:41] We can compare the previous value with the current one, right? This gives us a kind of an escape patch of getting a unique copy every time and only adding a slice in time. So yeah, the current will actually persist across renders until you update it. It is only getting updated when we choose to update it.
[00:09:00] If for instance, I took out this line right here, it would just stay the same value across every render. It is only happening because I am assigning it. Right? So it gives you the ability to get some of that same ability to like reference, like a persistent value that you had from a component class you now get with a function as well.