Current section: Optimize Rendering 33 exercises
solution

Custom Comparator

Loading solution

Transcript

00:00 Let's get started by re-implementing the comparator the same way that it's implemented in Reactor, at least in a way similar. So we'll say our comparator is going to take our pre-props and our next props, and that's going to return, let's actually have it return the default. So

00:16 if you didn't even have memo, you want to return false if you want it to re-render. So return true if you are like, yeah, we can optimize this. And so if I return false, you'll notice that we are re-rendering everything as we would expect. If I return true, then you'll notice

00:34 the re-renders are not happening. Okay, so that's one way to make it super fast and make it so it doesn't work. So we do want to be a little bit smarter about this. So let's return the previous

00:47 props.index is equal to next props.index and pre-props. There we go. And we'll do the city, and we don't want to do the city ID. The way React does it is just the city. And then the

01:05 selected city and the highlighted index. And also, we don't want to forget, come on AI Assistant, we don't want to forget the previous props.getItemProps, that function. Also, if that changed, we don't want to call an old function, right? So yeah, we need to make sure that is

01:23 being handled. So this is basically the default behavior of React. So now it's all re-rendering. If we did the profiler, you'll notice we get that same behavior with all of the things re-rendering when we're changing highlighted states. So yeah, definitely something that we want to fix.

01:41 And the things that are changing are selected city and highlighted. Well, actually, it's just the highlighted index, but we'd have the same problem if we change the selected city. So this right here is the reason that we're re-rendering, even though it's memoized. But if we take a look at the implementation, you'll notice that our isHighlighted state is determined based on whether

02:00 the highlighted index is equal to our index. So really, we only need to know whether isHighlighted is going to be different and whether isSelected is going to be different. And so right here, let's get rid of that. Right here, we're going to say, hey, did the selected city change or did the

02:16 highlighted index change? Or rather, was I previously selected? Was I previously highlighted? And did that state change? So we're going to say previousIsSelected would be previousProps.selected

02:28 city.id is equal to previousProps.cityId. And we'll say nextIsSelected. So was I selected before? Am I going to be selected now? And then same with highlighted. PreviousIsHighlighted and nextIsHighlighted. And that is all that determines whether or not we're going to

02:48 need to re-render. So this highlighted index comparison now can just be a comparison of previousIsHighlighted and nextIsHighlighted. And for the selected city, that's previousIsSelected and nextIsSelected. So if I was previously selected and I'm still selected, then I don't

03:09 need to re-render. If I was previously highlighted and I'm still highlighted, I don't need to re-render. And all of that logic continues. If I wasn't before, then I don't need to anymore. So now with that, let's take a look at our performance tab first. We're still on a 6x

03:24 slowdown right here. We record. We highlight. We unhighlight. And you'll notice the red is gone, with the exception of this silly red that I think is just the profile starting up. But yeah, this right here, it's still like it's taking a little bit longer. Maybe there's some

03:40 things we can do to optimize that a bit. There are. But it is at a 6x slowdown. This is remarkably great. And our optimization has definitely improved. So we can also take a look at the profiler to see if it improved for the reason we thought it did. And we'll notice we are only

03:58 re-rendering two items. So the item is the one that had its highlight state change, or both of them. This was highlighted before. It's no longer highlighted. And this represents the memoized

04:15 version of that thing, I believe. So that is the comparator function. Definitely an easy one to mess up. Because if we were to say, oh, you know what? I'm going to say selected city. Let's stick that in interpolation.id. And now we actually do depend on the selected city. And we need to

04:33 re-render when the selected city changes. But we won't. Check this out. This is silly. So I'll click on this. And now the selected city is in there. And if I choose this one instead, well, actually, it's going to select and it's going to update anyway. Maybe I should use a

04:52 different example for this. How about we do the highlighted index instead? Highlighted index. Boom. There we go. Okay. So let's unselect. Selection is cleared. And now you'll notice that the highlighted index is getting changed for these ones, but not for the others because they're not re-rendering.

05:09 Yeah. So you want to be careful about your comparator function because it's actually quite easy to break. But if you are in a situation where it's like, wow, this is a really tough thing to optimize, then it could be a perfectly good solution for an optimization. Great job.