Lesson Description
The "Memoization in the React Compiler" Lesson is part of the full, React Performance, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Steve demonstrates wrapping a function in React.memo to optimize performance. He explains how useCallback can prevent unnecessary re-renders and demonstrates using both to maintain static values and reduce component rendering.
Transcript from the "Memoization in the React Compiler" Lesson
[00:00:00]
>> Steve Kinney: But the problem with this is, one, if you mess it up for some reason, you could, like, let's say you omitted something from that array. Now, if React Compiler's whole job is to look at your code at runtime and find these optimizations, guess what else can do that? ESLint, right? So I have ESLint rules that would give me a squiggly line, partially because I'm also live coding in front of people and like wasn't willing to take the risk on a different topic later.
[00:00:26]
But like theoretically, couldn't we do the same thing? Right? And that is what React Compiler seeks to do. And the cool thing about React Compiler, and I've warned you, technically released candidate. Also like used in production for Instagram.com and I'm sure a ton of other places. Opt-in, also, you do not need to be on React 19 to use it. Yes, it is new. It is also built on top of all the primitives from Fiber.
[00:00:57]
So everything that uses Fiber, I think that's 17 and later from memory, are also fair game. So you can use it today, however, like, it assumes that you are doing everything by the quote unquote rules of React, which are probably parts of your codebase that you're not. So like the mature thing to do, and I've got a little like guide in the thing is like an incremental approach, right? Do not or pay the consequences, I don't know, do whatever you want, but what it seeks to do is analyze your code at runtime, kind of like all does and figure out where these things would have normally gone.
[00:01:36]
And do them for you, right? Hence why I'm not spending too much of our precious time together perseverating on this, because ideally, you should know how it works, you have an understanding, but also, hopefully, it is like it is in stuff like Svelte and Solid abstracted to the compiler, and maybe as long as, unless you can't find a weird edge case or you have some other strange thing going on, hopefully I aspire to be something you don't worry about all the time.
[00:02:03]
To kind of see it in action and get a nice understanding of how it works, there is this playground.react.dev. I'm going to turn off these tools for a second. This is obviously a somewhat silly example, but, uh, you can see that this is effectively what React Compiler will do to any of your code, right? And let's, yeah, let's start with the default one that they put in here because why not? On one hand, in this case, you could argue it is, uh, slightly more code, but not really.
[00:02:40]
So, the first one is you have this, we're importing this C, letter C from React Compiler, in this case, runtime, right? Obviously, if you're using the Babel plugin, it's slightly different. And what it does is, and you don't have to write any of the code, you're like, I don't understand what this is, and it makes my brain hurt. Good, you don't write it. You just write React, making believe you didn't know that, useMemo, useCallback and React.memo.
[00:03:04]
He says, this happens behind the scene. Think about it like those lanes with the bitwise operators that stressed you out. If stuff you, guess what, it's all electrons going through a copper wire at the end of the day, and a bunch of ones and zeros. It's very stressful to lower down the stack you go. But what we do here is we say like, hey, with the C, we're going to say we need a effectively an array of one thing, right, which we'll store in here.
[00:03:28]
This is effectively an array. And we're going to say, if the first thing in that array is this like, sentinel because there's nothing really going on in this, right? Give us back the component, cash it. Right, and then never even run this again. Right, because it's putting us the first thing on the array. The next time it runs around, the first thing on the array is this like literal thing that doesn't change, then go ahead and return it.
[00:04:00]
And we're done here. Now if we give it like, let's say a, like, we'll call this greeting, and we'll say that it takes a name. And we will then. OK, slightly more complicated. Uh, we effectively though, it has not changed too much. You'll notice though, there's none of these like arrays. None of these like functions, we are using much cheaper abstractions here, which is we make a two-element array.
[00:04:44]
Right here, uh, too much. We make a two-element array. Right, we go ahead and we begin to say, hey, is the first thing in that array equal to the string name. Right? If we're not equal to it. OK, if so, we go and we run the child function, so this is effectively React.memo. Right? Just a much simpler version, and we save it to this T0 and we put it in the array. So for name. For the name we pass in, the first thing in the array, the JSX that would have come out is the second thing in the array.
[00:05:29]
Right? So if the name is not the same, go run the child component. The new name, the new return value. If it was the same. The return value is just the second thing in the array and we're done. So it effectively is using React.memo, but even a cheaper, simpler version because it's not calling a function and comparing this object with that object. It is saying like, I literally stored a reference. I will update the reference.
[00:05:56]
If they are the same, I'm always going to do the right thing. Mechanically similar to React.memo. Without instantiating new functions, calling a bunch of stuff, it is just doing very clean value checks, effectively, incredibly simply, and it will do this. Effectively across your codebase for when you are following the rules, right? If you start doing weird stuff. It's just going to be like, I have two options here.
[00:06:26]
I can either help, but if I help, I might make things wrong cause it's like, it doesn't understand what's going on, at what point it bails. Right. And it's really only checking against like inputs and outputs, right, for stuff like where you know that like, you need to do this special thing and maybe has some side effects, like, and this is why like when people are like, I have this clever hack that's going to be a thing, sometimes swimming upstream is not beneficial for you, right?
[00:07:00]
Cause it might solve that one unique case and then opt the entire subtree out of any optimization ever again. And so was your hack. More performing. Less performing. You can measure and find out, you have the tools, and that's where that kind of measuring versus like, I'm going to try some crazy stuff becomes interesting. But the cool thing is, it's, again, one, the amount of work one needs to do is very little.
[00:07:27]
I will show you. We'll look up the real syntax thing, but you pull this in, and now what's going to happen is at build time, it's going to run it through this Babel plugin, which is going to analyze the code and do the things. That's it. Right now there are ways to opt in and opt out, and so on and so forth, right, like that are very nuanced for what you need to do. But by pulling this plugin, let's look up the real syntax.
[00:07:56]
Oh, it was an array inside of an array, like the way Babel does it, not the way Vite normally does it. OK. So, good thing I, there, if you watched me for a period of time, I was never going to get that right because again, I do it once a project. It's like I have to look up the last VS, uh, tsconfig that I did from the last project and ported it over. For the first decade of being a software engineer, I definitely had to look up how to put a style sheet in an HTML because you do it like once a project.
[00:08:23]
Anyway. So you pull this in, and then again, you have confirmation of opt-in, right? You know, there's some tweaks, again, if Greenfield is going to be a different set of tweaks, obviously, if you are doing it on a like existing legacy project, you want to be able to opt in where you choose to use it and do it progressively over time. But the fact of the matter is, by running your project through the React Compiler, you will get a lot of the memoization stuff for free.
[00:08:52]
Again, there is probably going to be a migration process, and I have like some notes on that in the repo, like, and the reason why it's still worth discussing a little bit some of the memo and callback stuff is there is still like a time and a place for all of that that is important and like worth doing and like you might not be able to do it all at once like unless you're starting a brand new project tomorrow, at which point like absolutely.
[00:09:22]
But you know, over time, you can begin to kind of opt-in components with this use compiler directive, which you're like, what is that? It's an old move from back in the ES5 days, which is that doesn't do anything. And so you put it at the top of the file and it doesn't break any legacy code, but new things that go looking for that, like a compiler, for instance, sees that string that doesn't do anything to runtime code for anything that doesn't know about it, and then opts you into that mode.
[00:09:49]
And so now for this like set of components, you will be opted into the React Compiler. Great, wonderful. So, obviously like figuring out the heuristics and where it's important and knowing how to use the tools, if you don't have full access to React Compiler is super interesting. If there are like kind of safe places you have to start migrating over, obviously, it is not only more performance than doing it with the hooks, but also obviously having it analyze all of the things and like making the correct decisions.
[00:10:25]
Is also good, but I would say, obviously if you want to opt out the compiler, you can. Surprise, and you know, you can opt in and out as time goes on, but yeah, the idea is like you can hopefully over time in the same way that like there was a gradual migration of class components to functional components, all sorts of things, you know, you've probably changed CSS libraries like four times at this point.
[00:10:54]
I see the smiles. They're smiles of pain, uh, you know, those things, but like you can begin this process. I think that hopefully, and this is like, you're like, whoa, this seems risky. This is at least a pattern that has been like pretty well trodden by like Svelte and Solid and like other large frameworks that are used like Svelte powers Apple Music, and again, Instagram.com is using React Compiler.
[00:11:21]
So like, you are not the like test subject in this case, right, uh, but that said. A certain amount of caution because just flipping it on everywhere can have some unintended side effects. So it is an opportunity and then ideally as you move into it, then hopefully you can continue with it on. So, um, super awesome idea and like I think that like for a lot of this stuff, there's other things that you could do.
[00:11:46]
It is definitely like I find myself for my own projects, usually writing a Vite plugin for certain things that I need to do repeatedly. Or code generation or stuff along those lines. And so there are maybe patterns, other patterns that might be helpful for you as well. So it's a cool pattern too, but that's a different story, for a different day, but definitely worth checking out the playground and seeing how various like smaller components that you have might work.
[00:12:20]
We can even like grab, um, something from. Uh, one of our like projects, even if I grab, let's grab the like calculator card, and it's a larger card and like a larger component, and nobody wants to like fully read what I'm about, what's about to happen in here, but like getting a little bit of a like. A high level here to kind of see, OK, this now is making 36 slots that it's keeping track of. No, nobody wants to read this code one by one, but it's also figuring out the JSX that gets rendered, putting these things into values that it is checking the equality of, uh, so here's that calculator type, and this is, I grabbed the one that we did not optimize yet, right?
[00:13:00]
I grabbed like. I know we changed one. This is the unoptimized one, where you can see that it is starting to check to see like, hey, that's the third thing, why is it the third thing? Because it's the thing the compiler came across. I guess fourth technically it's the razor zero index. All right, if that's not equal to what got passed in this time, then go ahead and recalculate it. So it is doing a lot of the memoization in a much more efficient yet harder to maintain, but you're not maintaining it in the same way that all of your JSX was going through a compiler to begin with.
[00:13:32]
Right? All your TypeScript was going through a compiler to begin with too. And then probably getting minified. We are, I think, at a certain point, somewhat comfortable with not always being able to read the outputted code from Webpack or Vite, right? But I think looking at like, you know, even if every line doesn't make total sense, the kind of like patterns that we can see, I think shows you effectively, like how it works.
[00:13:56]
So it's not just like, oh, I turned this thing on, I don't know what it does, because like, everything has an edge case, even if it's probably not the compiler's fault, probably your app's fault, right? Somebody sometime did something weird that no one regretted at the time, and years later came back to bite everyone is every incident that's ever happened. No one put bugs in their code that caused an incident, right?
[00:14:22]
I've seen some of the wildest stuff from just like, the weirdest set of coincidences like all like aligning at the same time. We don't, that's why we call them blameless postmortems, unless it's somebody else's like a library, then you blame them. But nobody that you work with gets blamed. Cool. So that's kind of the, like the nice part about the React Compiler is that like, other than turning it on and like getting somewhat of a conceptual understanding of what it does.
[00:00:00]
There's not a lot more to it. That's like that was like the selling point, right, is that it seeks to take these things we would have done manually and come up with a heuristic to do it automatically, right? And again, you can opt in, so what's useful is, you know, turning it on, you know, evaluating the performance of a given thing, seeing like, does it do what you expect to do, so on and so forth.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops