React Performance

React Fiber & Rendering Q&A

Steve Kinney

Steve Kinney

React Performance

Check out a free preview of the full React Performance course

The "React Fiber & Rendering Q&A" Lesson is part of the full, React Performance course featured in this preview video. Here's what you'd learn in this lesson:

Steve discusses a React data structure used to track component instances called fiber and automatic batching introduced in React 18. Student questions regarding if there is a reason not to auto-assign keys and if you need to be cautious with the Context API are also covered in this segment.


Transcript from the "React Fiber & Rendering Q&A" Lesson

>> And under the hood, while this is all happening from 16 later, which is I believe hooks, yeah, hooks related to fiber. Fibers are just a data structure where it keeps track of component interests as siblings, all those things, and try to figure out how to optimize this as much as possible.

This is why stuff like keys are important. This is why the general kind of other advice that I would give you is, for instance, if something is mostly the same but for some reason you're like, I've got this crazy trick where I'm gonna switch it from a div to a span, those are the things where React's like I don't even know what's going on anymore, right?

And so this is a piece of programming advice I will just give you which is that really fancy stuff seems really cool, and the kind of more explicit stuff is on a long enough timeline, almost always better for both the computer and your friends. But yeah, fibers are how kind of React wires this all together.

It's the status structure, we can keep the kinda previous iterations, it has a structure that it's looking at. And this is why I say the whole, it's just a virtual DOM thing is less and less true these days. It's actually grown a bit since 2013. Imagine that, frameworks change over almost a decade now, right?

So yeah, there are lots of things but this is why the keys are important. It's what was the order? Do I need to throw away this entire list or table or what have you? Can I just insert one DOM element? Because sometimes I did this course on JavaScript performance a long time ago.

But sometimes it's actually cheaper when you're updating the DOM to just blow away an entire section and put it back, right? And sometimes it's cheaper to just add one to the end. And so if you do not give React the information that it needs, it cannot make good choices on your behalf.

And then you're like, React is slow. I'm like, is it React? Or are you making poor choices, right? And so understanding that there are complications and that the whole process in which it does this is not magic, is important.
>> Mine might just be a misunderstanding, but were you saying semantic HTML is worse than just divs for React or the other way around?

>> No, I'm saying if you came up with some really fancy technique of, in this moment I'm gonna change it from being a div to a span for this reason, it's gonna throw it out, right? Semantic HTML, great, consistently semantic HTML, like weird, dynamic programming thing that you did to impress your friends.

>> Out of place.
>> Yeah, is almost always going to confuse the very delicate set of heuristics that has been finetuned over the last nine years to help you.
>> So one or the other throughout.
>> Yeah, like the fancier you get, the more you're walking on the edge.

>> Is there a reason not to auto sign a unique key at least to handle the remove and change order to your list?
>> As long as it's consistent, right? For instance, yeah, bad ideas math.random, but, okay, right? That's a ridiculous bad idea. Other bad ideas, the array index, cuz that will change every time the array changes, right?

But that one seems like I don't have one, I'll just use that to get React to be quiet and leave me alone. But sometimes we have situations where it's like if you're usually getting something from an API, you usually got some kind of ID to work with, right?

But if you don't, then to your question, the right thing to do is around the time you get that array or collection or whatever, assign everything in their unique identifier. Map over it first before [INAUDIBLE] a React component. Give them all, even a standard integer that's not gonna change based on the where it is in the array or UUID, or grab the NanoID like library and just, yeah.

If you need to give stuff, if it didn't come for you with some way, shape or form, like it was just an array of strings that could have duplicates, right? Go through them first and maybe map them into an object that's got whatever that string was, and then a unique ID, right?

Especially if it's changing in any way, shape, or form. Which is like on a long enough timeline, assume anything like when you first wrote the code, this array never changes. If you've been doing this more than three months, it's changed on you. Right, so yeah, I think grabbing it first and putting a unique identifier from something in some way, shape or form.

I said this in a previous one, I got bit by this one time. We had actually an API with a unique ID and for some reason somebody else on my team had used the name of the templates cuz there's a list of templates, the name of the templates as the key.

But you could have two of those, you could have two templates of the same name, and it wasn't until I was like, we were doing a migration thing and I had to reinvent the thing. I was throwing a bunch of dummy data at it, where I had multiple ones and React went to a weird mode where things weren't changing or moving.

It didn't know what to update when cuz I had two with the same unique identifier. And I thought I had found some unique bug. And then my teammate walked up to me, looked at my screen, pointed at it and reminded me that it was not the case. But above and beyond performance issues, you could also end up with things aren't changing the way you thought and you're getting no error messages.

>> And run into similar examples of, I think it's a unique ID, but it turns out under some circumstances is not. If you do a search and the search result array comes back and there might be a link to the page for that search result. But if there are multiple matches on a target page and they both come back as a different search result, because they match different parts of the document-

>> Yep.
>> They might have the same identifier, so good.
>> Yep.
>> Good scenario to when you get the API response just uniquely identify each element and then render.
>> Exactly, if you don't get a unique thing, then you can give it to it upon receiving it and use that to track it.

Yeah, Mark.
>> So we need to be very careful with the context API as it lifts the state up for you, right?
>> Yeah, we spend a whole hour on that one. [LAUGH] I'm gonna do the spoiler alert. I'm gonna spoil it now. We're gonna do a bunch of things to make an app renderless, and then we're gonna add the context API to it, and then we're gonna start over [LAUGH].

So as we're going through that initial one just don't get your hopes up, right? So yes, the question was, does the context API which then sits literally, if you think about where you put those providers, you put it around the application component, right? So they will trigger all sorts of things.

Now, there are ways to solve for this. And one of the things that you'll notice that a lot of the other larger libraries don't have these problems, let's say hypothetically I'm gonna use context API, I may use like my own, I don't even need Redux, right? You'll notice flashes of green everywhere.

And you'll notice install React Redux, it doesn't. One, it's just optimized more than you did at the very first thing. And then, two, in React 18, Redux is structured differently in so far as the store external. And so it's not necessarily using all the hooks that trigger stuff.

It's actually using a completely different hook called useSyncExterna. That is mostly meant for libraries to interact with, right, that you could totally use to. And if we have free time at some point, I'll show it to you but like, yeah, using the context API, then you get a new set of things.

Luckily, in this workshop, if I might sell you on sticking out with me, we will run into that issue and we will address that issue, and we will solve that issue, and then will break it again, and we'll solve it again, right? Fun times, all right. Speaking of questions coming in that set me up for making promises, like I said before, we talked about automate batching so I won't spend too long on it now, but in React 18.

And if you notice, if you just bump up ]your React 18 from 17 to 18, and your package JSON, you will immediately get yelled at. Without polite warning in the console, which is like you're using React DOM.render, you need to use create route and then from that route render it, right?

That is an API change that actually opts you in to effectively some new functionality that gets you this. So if you use, I guess the other, it depends. Do you get automatic batching as if you've chosen to upgrade to React 18 and ignore that suggestion, then know you don't cuz you're still using React 17 earlier as React DOM implementation, right?

And so you get automatic batching if you use the recommended concurrent C supporting version of mounting the initial root node, Mark.
>> Yeah, there's a clarification on how this works. So is React rendering each component and then saving the result of it and then when it re renders kind of comparing the two?

>> Basically yeah. So the question was, it's saving the output from last time. Looking how it's changed. That is how it collects all the data for the commit phase, right? Awesome. On the topic of the automatic batching, which is before React 18, there was a way to like, there was like, forget the name was like unstable_batch updates, that might have actually been the name.

And you could use that and like React Redux used in other libraries used it like in the same way that before there was the context API that we all know and love. There was always legacy, never fully supported, always unstable one that all these libraries used originally as well.

And so there's this one that those libraries used. Now that it's supported in React 18 for everyone. I guess sometimes you need to, for some reason, give people the opposite. So if you for some reason, need to get out of automatic batching which you better have a real good reason like when that when that PR lands on my desk, I'm gonna have questions for you.

And if it's like I totally needed it for this very like the burden of proof is on you to use. Look at all the docs even frames it, like it starts out with a big warning thing. Using flushSync is uncommon and can hurt the performance of your app.

The burden of proof is on you if you choose to use this one, but I just want to do my due diligence to make you aware that it does in fact exist. If you need it, I've done my job, I've told you about it. If you mention my name in the PR, I will deny every minute of it despite the fact that this is recorded and live streamed.

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