React Performance

Reducing Rerenders

Steve Kinney

Steve Kinney

React Performance

Check out a free preview of the full React Performance course

The "Reducing Rerenders" Lesson is part of the full, React Performance course featured in this preview video. Here's what you'd learn in this lesson:

Steve demonstrates starting to reduce the number of times an application rerenders without memoization by pushing the state down. A student's question regarding if sibling components that share the same useState should be put somewhere else when using Context API is also covered in this segment.


Transcript from the "Reducing Rerenders" Lesson

>> So, we are going to take a small little app and figure out how to now reduce the Rerenders a little bit. It is there, and you can see right now in the initial version, it not only, one point if I keep typing, I can get it to go even to a yellow, right?

Cuz it's just a lot of things are changing a lot, right? And what we wanna do is, to be clear, you want some change when something happens, right? You just don't want more than you need. It's like as much changes to the DOM and to the renders as you need as little as you can get away with, right, unless the act of stopping it is more expensive than just letting it go, right?

In this case, it probably is cuz I didn't hide any ridiculous functions in there. I just wanted something where there was lots of glowing boxes. So in this case, doing any of that will trigger all these things. It seems a little ridiculous that typing in an input field would make the whole app go wild, right?

So what we'll do is, first, we will look at some ways to just kind of work with our component structure without using any memorization stuff at all, without trying to stop anything ourselves. And then after that, we will go ahead and, okay, there's some things where we have to step in and go, this doesn't matter, this does, right?

And again, this one is not a particularly so out, but it has enough of the patterns that we would see if we measured it. Could I put things to make it slow, sure. But yeah, try to parse outlook 2003 emails into an ASD, and you'll find your slow places very quickly.

It's the same methods to solve it either way. Awesome, so I'm gonna switch over to that app and kind of do some changes as well. Sure, he's whatever port you want. And we'll open up the tools, and we'll verify what my very fancy screen recording already told us, that things rerender quite a bit in here, right?

Every keystroke changes everything, right? And let's take a look and see, let's see if we can acquiesce some of the issues here. Then we can see that application is rendering, which runs as the header. Nice ways you can hover over renders or items list, both of them over here.

Those are the intergrain, a bunch of items to rerender as well. They're getting new props, that's cool. That seems interesting. That's probably just function, so they're gonna call eventually, because each one so on and so forth. And there they are. They exist, things ago. So you guys see the color kind of signifies how much you need to deal with it.

But let's go take a look at the app and see what we immediately see just by staring at it. We know that it's application at the very top root of everything that is causing the issue. But let's take a tour of the absence. We're gonna spend a little bit of time on it as well, and then probably some things will jump out at us along the way.

We could argue that that could go in one of those functions as well, but it's literally just reading a JSON file, cool. We got a set stage and empty string. We make all the different functions that we need cuz we don't have set items until we're inside the function.

Right, we don't have the hook for changing the state. I can't put that outside, otherwise, all of the, how do you immutably change an array, that lives over in another file because it didn't need to live in here. But I need to then set items accordingly with everything it has.

Awesome, there are some things that strike us at, do I have to filter these every time, probably. You'd have to filter them somewhere, right, if they're changing, right. If you can confirm that they haven't changed any way, shape, or form, but that's the same as mapping over them.

So, okay, unpacked, cool, cool, cool. And then we're just using regular prop drilling here. So itself doesn't really care about removing an item. I mean, it could, right, but that's actually an interesting refactor. We could too maybe, but they pass them through. But the first thing we saw was that typing in the input field was somewhat problematic.

And so, we look, this is where we talked about in the very beginning when we saw that picture of the tree, right? Here, we have, whatever that new items name is going to be, that draft state, whatever they've currently typed in the input field, that lives in application, right?

And we saw that application was the one triggering everything in this initial case. And some things will live in application, right? Cuz again, in React, generally speaking, whatever the shared state has to live at the highest most node that all of the components are using it, have in common, right?

So at some point, that is application for things like everyone's favorite current user, right, and replace along those lines. So, that trigger stuff. And sometimes the name of the game is, before we start smothering stuff in a React app or use or component update or anything like that, it is like, could we get that tree smaller, right?

And my hypothesis is that we can, because I am passing in that draft state to this new item component. I am passing in the set new item name, and I am passing in the Add Item. And you might be, hey, this might seem a little silly, but it is very, I saw a code last week where, yeah, they didn't break out into a component pass every day, and they did have the input field just in here, right?

And that is, the refactoring sometimes the name of the game is, take what was just literally just some innocuous HTML to look totally fine. But in pushing that state down and by taking some just HTML JSX and refactoring into component to push the stuff that only that little chunk cares about down a level.

So it becomes, remember that graph we had, that one that was just by itself and didn't really care about anything? If that one was changing on every keystroke what the draft item name was, the rest of the application doesn't need to know until they hit Submit. And then, yeah, you've added a new one to the list.

We gotta update the list. But sometimes the name of the game is, yeah, and I just didn't want it to sit there. And like, let me copy some HTML and make a new file. So it's made for us. But sometimes the name of the game is taking just HTML that seems like it's not hurting anybody.

And I don't need to break this out into its own component, and maybe you don't, right, that wasn't particularly slow. But the pattern in this case is making the component, pushing that stuff down. So it is now on a lower node and not affecting one of its siblings.

That would cause everything to rerender. Cuz that could be further down that tree, which is now getting thrashed all the time, whether generating random numbers constantly, random colors, or what have you. So in this case, the refactor is pretty easy. We go into this new item and we say, what if?

It says, you are the only component in my app that cares about what's in that input field. We care when it hits event, I'm here for it. When they hit Submit, please tell me about what it is. But in the meantime, why don't you keep that information to yourself, right?

And this one gets filed under. I think I told you there was the things you should probably maybe always do, things you should definitely always do, run in production mode. Things you should probably maybe always do, which is something like this, which is just pushing it down the tree, not memorizing anything.

You're not doing anything, you're just taking anything that was happening and having its blast radius. It's like taking your worst friend and not letting them hang out with the ones that you like. You still wanna hang out with them, but not all the time. It's how Mark feels about me.

And so, we kind of have that state in there. And that will go ahead and keep track of all that, and now I can get rid of it out of application.
>> So you've had sibling components that you would essentially be creating that same use-state in each one.

Would you then put that in context somewhere else so you don't have to have the same line of code in three different components, or 18, or whatever?
>> Yeah, if you have shared code, then all of a sudden now you play the game of, pull it up the tray.

The thing about using a context API is, if you're pulling it up the tree, right, the context wraps. You and your entire application doesn't [INAUDIBLE] we typically. Well, context API, put on the entire application theoretically. And maybe you should by maybe definitely like, if only a subset of that tree needed that context, wrap it around that.

But there's really no difference of pulling that up and wrapping in context, that's just a way to more conveniently pull it up, right?
>> So that's essentially where we started.
>> Yeah.
>> Right, yeah, okay.
>> And so now we've gotten rid of that one.
>> And let's make sure my code compiles while Alex asks me a question.

>> Yeah, what about the most obvious thing, wrapping the git original items into an anonymous function here.
>> That'll do it too. That one wasn't particularly fast, we can do it, both work. Cuz it's tricky, cuz this thing isn't actually that. So it is rerendering all over the place.

So now we can say, and if you look at the green lines, what's the yellow if I really slam on the keyboard? What's the only thing rerendering? Now it's its own subtree, and it's not bothering anyone else, it's not talking to application. Now, if I hit add, right?

Okay, but that's worth it, that's where the items live. If it was an application, that is the common denominator of the pact in the unpack list. But that input field wasn't. That is one of the very first easy optimizations that isn't harming anyone, right? Push that, say, down to the lowest common denominator that needs it, and lift it up as high as you need to, but as low as you can get away with, right?

Instantly just makes the tree shorter without calling any crazy Malwise functions, or any kind of cache, or anything like that. Just trying to limit its blast radius and what renders it causes, immediately kinda solves that issue.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now