Check out a free preview of the full Intermediate React, v3 course:
The "useCallback" Lesson is part of the full, Intermediate React, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates how to use the useCallback hook with React.memo to re-render an expensive computation only when absolutely necessary. The useCallback hook takes in a function and returns a memoized version of the callback only when one of the dependencies are called.

Get Unlimited Access Now

Transcript from the "useCallback" Lesson

[00:00:00]
>> So you're gonna look at this and you're gonna say, this seems a lot like use, what we were just talking about, useMemo. So useCallback and useMemo end up being functionally very similar. And in fact useCallback is implemented internally with react with useMemo. So that's something to just keep in mind, that these are pretty related.

[00:00:24] So first thing I'm gonna do is I'm going to change my memo to be back to like one so this is not crazy anymore. Okay, and then we're gonna go back here to Callback. All right, so, here with useCallback, I have the time that's going up every second, all right?

[00:00:43] So, this component using an effect here, is the timer is going up every second. So, this component here re-rendering every single second, which means that everything inside of it needs to be pretty performance because if it's gonna hang it's going to make our clock look like it's not, moving up every second.

[00:01:03] It's not gonna look like a clock, right? But I have this component down here that's also using this Fibonacci sequence again. So when it's at one, it's not a big deal. But if this was at, again 30, we can just put it up here at 30, if we want to, or 40.

[00:01:22] This will take a second to re-render. But notice that this is still counting up at a normal rate. Let's go dig into that a little bit. Like we talked about before, whenever we render a parent component, the children component are going to re-render as well unless we have some sort of like should component update that tells it like wait, do not re-render me.

[00:01:44] So one of those things that can kind of be a problem is, in order to get access to local data, we have to use closures, right, and whenever we're making closures, we're creating new functions in the process every single time. Well, here's kind of a problem with this.

[00:02:00] What happens with this Fibonacci sequence function lives in the callback component. But it's called in the expensive computation component. Now, it's a very specific use case and if you're wondering why would I do this? And the answer is frequently you can code around this. So I invented a situation this is what happened, but you could definitely code around this and not do it this way.

[00:02:23] But I'm gonna show you how to make it work anyway. All right, so I have callback component, and I have the count. These both live in callback component. And so I have to use Fibonacci here, because that's coming from the callback component. But that gets passed down into the expensive computation component which is running the compute here.

[00:02:49] Now, this is a problem because if I don't, if I'm providing a new function every single time to this useCallback component here, sorry, to the expensive computation component here, this is going to re-render every single time that the time advances, right? And if this is 40 that's a big problem because it's going to try and calculate the Fibonacci of 40 every single second.

[00:03:18] And like, I would take this out so I could show you what it looks like but let me promise, it would just hang up the entire browser and we would never get it back. Right, just take my word for that if we were not using useCallback here with the Fibonacci here, that this would re-render every single time and then we would have a big problem.

[00:03:38] So what does useCallback do? UseCallback takes in a function here, right? And it takes in some sort of dependency thing here, which in this case, we're telling it, hey, Fibonacci never changes, so don't worry about it. And this way, it's going to give it back the same Fibonacci function.

[00:03:56] So this one here, it's gonna give the same Fibonacci function back every single time. So therefore, this expensive computation component gets the same function which it's gonna say then, okay, I do not need to re-render. That's the the functional thing here. We do have to talk a little bit about memo of why that's important.

[00:04:18] But do you understand the gist of like we're trying to give it the literally the same function every single time so that react doesn't think that the function is changing. Because if I give it Fibonacci and then I give it a second copy of a, it's of Fibonacci but it's a different instance of it.

[00:04:34] It's gonna think it's like these are different things, right? It's just like how, well, it's basically this. These are two different functions, right? Or maybe a better way of putting this is function A, Function B. A, now it's upset at me. So I have function A here and I have function B here.

[00:05:22] They're functionally equivalent, they do exactly the same thing, but they are not the same thing, right? They are two functions that are separate that do precisely the same thing. And that's the thing that we're gonna run in here with Fibonacci is that we're gonna have two different Fibonacci's that are functionally the same function, but are actually two different instances of the same function.

[00:05:40] So that's what useCallback is doing here is it's giving you the same copy of the same function. So in this case, it's gonna give you A every single time an A is triple equals to A. Okay, so we got that, now let's talk about memo. By default, this Callback component is gonna re-render expensive computational component every single time anyway.

[00:06:05] It's not gonna check to say, okay, did I get the same property as last time. It's just like, you know what, I don't know what they're doing in there, they could be doing weird stuff in there. In this case, we are doing weird stuff. We're putting new dates in here, so this actually does change every single time.

[00:06:18] What memo does is it's like all right, I'm gonna check the properties, and if compute and count come back the same as last time, I'm just not gonna re-render it, right? So it's gonna check the props. If the props stayed the same, then it's not going to re-render.

[00:06:34] That's what memo does. If you've ever used react before and you've heard a thing called a pure components this is the same idea, right? So a pure component is the same idea of like if the properties don't change then the render is gonna be the same so you can just go ahead and use what it used last time.

[00:06:52] Memo is just that but for functional components. So between using memo and using useCallback here, we're able to prevent this from rendering every single time. In fact, you can see here in rendering the last time that this rendered. The last time this rendered was now two minutes ago.

[00:07:17] But if I click current count so that the count here does change, so I click that, it will take forever to re-render. Notice that this last last few render is gonna update and it did. But it's not re-rendering every single time because we used memo and useCallback together to prevent that render from happening.

[00:07:37] Very specific performance optimization here. Again, I've never had to do it professionally, but it does exist. You might find yourself in a situation of like, I have to calculate the Fibonacci sequence and I also have to have a clock and I don't know how to have that at the same time, right?

[00:07:52] If you find yourself in that, you'll be like Brian told me about this right? [LAUGH] Until then you're gonna be like, I'm just gonna file that away under like probably not gonna use. So there's definitely a lot of ways to code around this. One of these is that Fibonacci definitely does not have to live inside of callback component.

[00:08:13] In this case, it's a pure function the sense that it takes in an n and returns a number. So it actually is not referencing anything inside of here. So yeah, you totally could and that would be totally fine. And then we would have to use useCallback. We wouldn't have to use, we would still have to use memo but we would not have to use useCallback.