Paul: Hi there, and welcome to PodRocket. I'm your host Paul, and today we're joined with Tejas Kumar. Welcome to the podcast, Tejas. Tejas Kumar: Hey Paul, how's it going? Paul: I'm excited for our episode today because we're going to be getting into some React guts, into some internals of React. So, Tejas has very willingly come on this episode today and we're going to get into React Fiber, some of the internals that we don't usually talk about. But before we get into that, Tejas, are you a React guy? Is that your bread and butter or do you come from a different area? Why did you come on? You're like, "Oh yeah, let's talk about this thing that a lot of people don't get into, the guts of React." How do we get to this point? Tejas Kumar: That's a really good question. So, I'm not a React guy. It's not my bread and butter. I'm just a curious person. I like exploring things and when I was a child, I used to learn by taking things apart and then, "Oh, how does this Lego death star opposed to be the Lego death star." This kind of thing. And so React is the most popular way to build user interfaces, I think on Earth, on the web anyway. So, I'm like, "Okay, this is cool, but what's actually happening?" And if I wanted to build it myself, how would I do it, right? So, it's just a curiosity thing. Of course, none of this is actually needed to use React, at all. You just use it to build great stuff. But I'm just curious. That's why. Paul: Right, yeah. And I remember before the podcast I was asking you like, "Oh, what do you do?" And Tejas was like, "Well, I do a lot of things." So, it's not your bread and butter, but it's something that you've come to tool with, foster curiosity about. Getting to that point where you were curious about it was because you yourself were building applications or helping other people advise them in building applications. Tejas Kumar: Yeah. So, I started my career as a front-end engineer, and I've been doing front-end for very long and then I pivoted and did backend and ops and all of these things. And lately I've been just more into management, but I've used React a lot and I still use React a lot to this day. So, I think that's probably why. And part of now as I've moved more into management, my role has been more so on the understanding trade-offs while also mentoring people. And that's why, yeah. Paul: Now, you're more in the managing space. Do you feel like this topic that we're going to be getting into, which is the guts of React, the fiber, this deep knowledge, is that something that, from your bird's eye point of view is missing from a lot of front-end engineers? Tejas Kumar: Yes, but it's not a problem that it's missing, right? This is not information that people need to know. People could completely not know this and miss even this podcast episode and the technical details of it and their careers will be fine. This is really nothing people need to know outside of maybe the React core team or, I find it interesting because it does help me write more fluent to React. It helps me personally, but I don't ... People who don't know this could just go through life and build great apps still. Paul: From my point of view is, you come from the front-end world, I come from the backend world. When I want to go tool to system, you can add a module, you can add a whatever file, but if you understand the end-to-end of how something's working, if you're part of the core team of two or three engineers, when the thing gets built, every feature you add is going to be intentful and purposeful in every line you write. I mean as long as you're still doing your job correctly because you're able to wrap your head around that. And I think that maybe this might end up in that same basket of yeah, you're writing more fluent React because you're embodying the ethos of how the system's designed. Tejas Kumar: Exactly. Versus it also prevents you from, I've heard earlier in my career, I heard a lot of people talk about you're fighting the framework. I think when you understand certain things you're like, "Ah, okay, so this is the more React to you way to do something. Particularly, there's a lot of confusion about, so React has this thing called useMemo like a hook which will memorize a certain return value of a function for you. There's a lot of confusion about, among most people I talk to is when to use it. When do I memorize something versus declare something new. And a lot of people I've seen tend to over-optimize. They'll put everything in useMemo, which is arguably less efficient than just having certain values be certain values. And when you understand the guts, you kind of understand the nuance of when to memorize what based on the render loop, the work loop that's happening. So it does help, but some would say then these benefits and performance you get from using useMemo fluently are insignificant, more optimizations and they don't matter and so on. So it's a very interesting space. Paul: Well, I think those types of optimizations, at least in my experience, their benefit is reaped. When you are solving people problems, it's like how do we expand on the code base? How do we onboard a new engineer? If you can figure out something with just the framework's docs and reading the code, you probably did things, you probably used things correctly. So anyway, we've been building up about why this is important and the guts and why we're going to talk about it. Let's get into it. Let's get into the guts. So we're talking about React Fiber today. What is that Tejas? What is this a section of the core library? Is this a new way to think about how front-end life cycles are arranged? Please fill us in. Tejas Kumar: Yeah. You're a backend developer, right? Paul: Yes. Tejas Kumar: So you would like, maybe not, I don't know, but in gaming there's this concept of double buffering. Paul: Yes. Yeah. Tejas Kumar: It's like that, right? Not a fiber in itself is just a data structure. It's a big object that contains state that maps to a tree of elements. This tree of elements describes what you want your UI to be. It's a very declarative description of what you want your UI to be. And then React takes this description of what you want your UI to be and does the work of reconciling that with a host environment. This is usually a browser, but it could be a mobile device, it could be a command line interface, it could be whatever React render you are using. But a fiber is just like this unit of work that is used in reconciliation in the work of reconciling your description of elements that you want versus the host environment. And the tree of elements is written in a very declarative way. If you work in the office space, it's kind of like a Kubernetes manifest. It's like, I have service, this is the configuration Kubernetes go make it happen. Paul: Okay, so could I think about a fiber as an atomic operation to get me one step closer to the final physical state? Tejas Kumar: Yeah, it's not an operation but it's a thing on which an operation happens. So a fiber is just a big JavaScript object that has state on this thing was created here. The state full node of this thing in the host environment is this. It's literally just a massive key value object on which operations happen. Or another way of saying that in the React functional language is it's a single unit of work on which effects happen to speak functional programming. So React will take fibers and perform effects on them. Effects like placement, putting it in the DOM or effects removing them, effects changing them. Paul: Are the fibers sort of aiming at being a holistic representation that iteratively get changed to get us towards the end state? Or are the fibers more parts of a hole that individually are going to be operated on to bring us to that final state? Tejas Kumar: Yeah, that's a really good question. They're both. So with in React since version 16 or currently in version 18, this notion of the fiber tree, there's actually two fiber trees and they're literally just, you can think of them as trees of fibers with leaves. There's two of them at any given time. One is called the current tree and that is actually the tree of fibers that gets painted onto a host environment in the browser. And there's an alternate or work in progress tree and it's literally just a linked list, a tree of fibers wherein the work in progress tree has operations done on it that reflect the desired state that is then switched with the current tree when what is called the commit phase happens. So to simplify, if your current fiber tree is a counter application with a number and an increment button, then when you click the increment button, React does the work of incrementing your counter. But in this other tree, in the alternate tree that is not rendered on screen, it's just in memory, it's detached from the browser. It will do the work of literally going through each fiber that is each node in the tree and marking them, this thing should be updated, this thing should be updated, this thing you can skip, et cetera. It's marking flags of what should change on the way down recursively. And on the way up it will literally construct a tree of what will be the DOM in the browser. It will construct this tree by attaching things to each other until the host is reached until the top is reached. And when this tree is constructed in memory off the browser, that then the commit phase is entered. So what we talked about before the commit phase called the render phase is you're doing the work of marking updates and attaching things and then the commit phase is, okay, we're done. Let's put this thing in the host environment. And that's effectively in React that's switching a pointer. So there's like a fiber root node and internal React data structure that points usually to the current tree that the user is seeing. But after the work of reconciliation is done on this detached tree, the work in progress tree, the pointer of what is on the screen is switched and the work in progress tree becomes the current tree. And you see the update on the screen. That's very high level how fibers work in the React Fiber reconciler. The reason for this is to allow interruptions because sometimes if there's work being done you and a higher priority update comes in. For example, user type something in a input field, you'll want that input field to update instantly. And so if there's some other work being done in this kind of detached tree over here, you can throw that away because the actual thing the user is seeing hasn't changed. So they're not going to end up in some Frankenstein state. Paul: This kind of reminds me of the server-side rendering dance that happens with a framework like Next or something like that where you have two different state trees and then there's a reconciliation step between them. And you said that one of the main purposes of this is interruptions. Tejas Kumar: Yes. Paul: To allow. Now, is that interruption allowed at any phase which in the reconciliation or is there a specific point that the interruptions usually interrupt, for lack of a better word. Tejas Kumar: Yeah, so the Fiber reconciler works on two phases. There's a render phase that commit phase and as we've talked about, render means just mark everything for updates on the way down and build this tree on the way back up that is interruptible. But once you get into the commit phase, you're literally putting stuff on the tree that is not interruptible, but thankfully commit is quick because it's just switching a pointer. It's not really doing any CPU intensive work. All of the CPU intensive work happens off the screen and so it can be thrown away if it takes too long. This also then allows some type of fallback. For example, if React schedule some work to be done on this work in progress tree and the work is taking longer than a certain timeout, it can bail out halfway and show a loading spinner like, "Hey, this is taking longer, show a little spinner and then continue that work." And then once the work is done committed. This is possible with the Fiber reconciler, the legacy reconciler didn't allow this because it was called the stack reconciler and it literally worked a stack data structure. It had to do things in this sequential order. Tasks were pushed onto the stack, and they had to be popped in order. So if any higher priority work came in to be done, you just have to wait and you would have these unresponsive user interfaces. Paul: Kind of makes sense of his design that way though because it's really a traditional, if I were to go make a render, it's like you put things on and you take them off in a deterministic order and we are all used to thinking about stacks. Tejas Kumar: Yes. Paul: As a way to store and access information in a deterministic way. But that makes sense to me now why this is called a fiber, because it's really a more of a two-dimensional set of tools that we're working with here. Tejas Kumar: Exactly. And if you consider any user interface and your interaction with its geared more towards an interruptible context switching type of workflow. We never do things sequentially though. We think about it that way. Paul: Yeah. It's our way to grapple with it mentally. Tejas Kumar: Yes. Paul: So the fact that this isn't a tree, does that allow, I'm trying to wrap my head around the fact that it is crazy to me that this fabric reconciliation step amongst many other things is being done 60 times a second. And that's nuts. That's a lot. That's really fast. So because of the fact that it's in the tree, and please correct me if I'm wrong 60 times a second, I don't actually know, but is it in a tree? Because you can take off sections of the tree, you can be like this whole object portion is not affected. The reconciliation steps only going to run for these nodes, these leaves. Tejas Kumar: Yes, exactly. Exactly, that's exactly it. Correct. And so because the whole point React reconciliation even is a thing, is because without reconciliation, what's the alternative? You throw away a DOM note and then replace it with another one, right? You're not able to update in place. It's very important to update in place because for, if we take the simplest example of a text input field, the moment you click into this thing and start typing your name, if you start typing like Paul, P-A-U-L, if you type P, the state of this input field at any given point in time or at that specific point in time is that it has focus and it has a blinking text cursor inside and the letter you just entered was P. And so now if you go to type A, that state is maintained and it becomes P-A and then U, et cetera. You need to update in place for that reason. If you just replace it with a new input every time, even with a new value, you lose your focus and you lose your blinking cursor and then the element isn't really focused, and you press the next character, nothing happens, and it becomes very messy. Paul: And by replace place, you mean within the tree you're literally just surgically going to that one node, you're taking it out and you're putting a new one. The rest are the same. Tejas Kumar: That's the alternative to what actually happens that you- Paul: Oh, that's the alternative. Tejas Kumar: What actually happens is instead of replacing the text note, you just change its properties. And so the Fiber reconciler recursively going through the work in progress tree will mark this text note as this thing needs an update, this is the update that needs to happen and it will continue through the tree. And then on the way back up, build this updated tree and then switch them to commit. It's very important to know that the state nodes, the elements themselves stay the same. It's just their properties that change and React, the reconciler will mark which properties need to change. Paul: Got you. Okay. So it's a property-based control versus a whole root level node control. Tejas Kumar: Yes, because if you replace the entire node, you lose its state than the user interface stuff. Paul: Oh yeah. See I've had no idea how any of this stuff has worked. Yeah, I'm learning so much on this podcast right now and it's like fantastic. Actually. We have a lot of React podcasts, we've done ones on writing good React writing tests and React, like you said, it's the ubiquitous framework of the day. If I were to write a UI, I would probably just turn to React also because I'm lazy and I don't want to go learn a new framework even though I should. Because learning is how we are always improving. But if people want to go learn more about React, check out our other PodRocket episodes. We have quite a few on them. So if you want to get more in the guts are in the weeds or get ideas. Tejas Kumar: Yeah, there's also blogs on, I think it's the LogRocket Blog. Paul: Yeah. We have quite a few random articles that people have found very helpful. So... Tejas Kumar: Yeah, there's blog posts. There's blog posts about exactly this, about React guts on your blog as well that people may find helpful. Paul: Yeah. If you're listening, you want to find more, please go check them out. So if somebody didn't know myself, didn't know anything about Fiber, the React Fiber reconciler, how it worked, and when we entered this podcast, you were very much of the opinion of you can be amazing and you will never know about this because this is a curiosity sort of thing. So having learned this as if you wanted to employ this to write clear React, is there a tangible example in your experience that you can think of about, now that I knew this, I did this thing differently. Tejas Kumar: Yeah, now that I know how the Fiber reconciler works, I actually do, the biggest, most abstract change I've made is that I don't think too hard about performance because I know enough to know that it is literally the entire job of React to take care of my components and reconcile them in an efficient way. So I used to be very pedantic about most performance work, especially also because now React is working more towards a scheduled concurrent style of rendering where tasks that are very CPU bound and take a lot of time are being scheduled in a way that some have priority, some don't, et cetera. Such that my slow tasks aren't going to impede my apps as much as I think they are, if that makes sense. So it sounds almost controversial to say, but I think less about performance as I used to, knowing that React has my back. Although of course sometimes if something is too slow, I'll use a profiler, I'll check the flame graphs and fix it, but it's not as preeminent as my mind is. It would have been otherwise. Paul: Do you think that there are any bugs that you've come across that having this new context, you've been able to look at the flame graph with more efficacy or something of that sort? Tejas Kumar: I think, no, I feel like a simple bug that, well it looked like a bug, but something that I thought was a bug, but I didn't understand was why, for example, the rules of React Hooks apply. I don't know if you write a lot of React, but with React Hooks specifically, you can't for example, have them be conditional. I was like, "Why is this?" And when I understand the internals of how hooks actually work, I did a talk on this once and everybody in the room was like, "Oh." So understanding the internals has helped me understand not really the bugs, but why things are the way they are. Specifically, why I'm not allowed to nest or have hooks that are conditional. Paul: Is that the talk that you gave at CodeGen? Tejas Kumar: No. Paul: No. Okay. That was another one about Hooks. Tejas Kumar: Yeah, there's a talk called Deconstructing React that I did that is pretty fun. I was not prepared for this at all. It was just... Paul: Those are the best talks every time. Tejas Kumar: Yeah. There was a speaker who didn't show up or something and the meetup organizer was like, "Dude help." And I was like, "Okay." And so I just decided to try to polyfill React. So we never imported React, but we just built something with React. But JavaScript told us like React isn't defined. So I was like, "Okay, let's define it iteratively and just create it from scratch." And we ended up doing that and then understanding why it is the way it is. Paul: So the big takeaways that I'm getting from Tejas is like, this is a great tools React has become very stable. It's allowing us to think less about performance and if we want to take a tangible thing away as a developer, it's focus more on your core logic and your abstractions. Because you don't have to think much about performance as much. Tejas Kumar: Oh, man, I'm going to get so much hate for saying don't care about performance. It's not true. I think performance is important and it's important to work towards it in as much as you're able, but I think at some point there's something to be said for trusting the library to do what the library does I've reimplemented or rather, I've done a lot of work that actually React does for me just because I didn't know that React was doing it for me. I think that's the bigger takeaway is if React promises minimal efficient changes to your UI, then to take that at face value and just focus on my UI, trusting the library that makes reconciliation go away or makes the problem of reconciliation go away. I think that's the key. But I think again, you're fully trusted, you have to know it. And I think that's the value of understanding the fiber architecture and fiber reconciliation and why it ended up being the next logical progression from stack reconciliation. I think that's key. Paul: That's a great takeaway. I feel like to even close out with, if the framework's doing something, let it do its thing as but with the caveat is make sure you understand. It's like with art, you have to learn how to learn the rules so that you can then go break the rules confidently. Tejas Kumar: Yeah, exactly. Yeah. Or not worry about breaking the rules because... Yeah, exactly. I'm with you. Paul: Heck yeah. Well, Tejas, thank you for your time. I certainly learned a lot in this session of ours. Hopefully, some other people can be turned onto the React Fiber and take that torch and run forward with it. Tejas Kumar: Can I test you, Paul? Paul: Please. Tejas Kumar: Can I do a quiz. So why again, does React use the fiber architecture instead of what it used to be? Paul: Well, because it has interruptibility. Tejas Kumar: That's so cool you actually... Yeah, okay. And how is it interruptible? Paul: Because if you're painting it to the DOM, that stuff's going to happen. We can't stop that. But they were like, let's try to break this into two separate phases. So when we're doing the whole logic, the CPU intense stuff that's happening off-screen, and that's a whole chunk of work that we can play around with. We can stop it, we can start it, we can sever it up and only do a portion of it. And it gives us a lot of flexibility in the speed and when things get painted to the screen, that's what I took away from this. Tejas Kumar: Yeah. Yeah, yeah. So doing the rendering off the screen and then putting it on the screen when it's ready. Yeah, that's good. Paul: Tell me, all right, I feel like I'm missing 10% Tejas. What's the last 10%? Tejas Kumar: Yeah, no, I think you're on the money. I feel like the 10% is the work of reconciliation gets done off-screen. I think you were right. And if it's CPU intensive, I think this is the missing 10% is the work can be thrown away because it's off the screen, nobody's seeing anything happening. The work can be thrown away, new work can be done to just put a loading spinner on the screen and then the work that was thrown away can come back into scope and be finished, and then the loading spinner goes away in favor of the actual finished work that goes on the screen. So I think the disposability of it and the ability to drop in a spinner after a given timeout I think is something that I didn't quite get in your recap, but I think you're on the money at least as much on the money as you can be in this time. Paul: Well, hey look, I got a stamp of approval of education, so that's great. Hey, I got my Tejas Kumar degree. I'll accept one a month in six to eight weeks. Tejas your name right here on our video chat is @TejasKumar if people want, is that like a handle of people want to go follow you? Tejas Kumar: Yeah, that's an underscore. Tejas Kumar underscore, that's my Twitter handle. I have a YouTube channel youtube.com/@tejask that's pretty much what I do all day every day, YouTube and Twitter. Paul: Awesome. Well, thank you for your time, Tejas. It was a great session. Tejas Kumar: All right, Paul, appreciate you. Thanks a lot.