Understanding React's UI Rendering Process

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
my name is Anthony Garrett Otto I'm a senior software engineer at cross comm a software development agency based out of Durham we make web mobile and immersive apps and I lead our front-end team I've been an engineer for little under ten years a full-stack developer but my focus has been mostly on the front end I've been working with react for just about four years now I've used angular and vue.js as well so it kind of like a well-rounded view of the ecosystem but react in particular took my interest I just really really enjoyed the way you create components and just the whole structure and process and I really really like the community that exists around react it was about a year ago this talk was born I had a bug I wasn't really understanding how something was being rendered and one of my I was getting a lot of rear Enders I didn't understand why because it was only happening occasionally and that began the process of me realizing like I didn't fully understand how react worked internally how we started with this weird HTML like structure and then actually ending up with Dom manipulations so that was a journey and it seems like you two are also interested in this so we'll go ahead and get started so this is I just want to give you a quick outline of kind of what we'll be going over today it's a little bit heady content so just kind of bear with me things will begin to make sense if you're in the middle something like this is so crazy it's just stick with me yeah we'll go ahead and jump in so we need to get on the same page for some things first HTML and the Dom I think most of us have a pretty good understanding of what this is considering the level of talk that we're in but I just I don't want to assume anyone's knowledge level so we'll just get some base information up play so reacts all several problems but if I had to boil it down to a single phrase or a single kind of statement react allows you to write maintainable a performant code using the concept of components component alais to focus on describing the UI you want rather than sitting on the details that the UI actually gets inserted into the page so just baseline understanding of kind of what reacts purposes and what we want it for and so let's just break that down further so that we have an understanding of like when we start but why reactors doing what we're doing we understand the premise behind it so what I'm trying to generate HTML I don't actually care how my nav or my buttons get inserted into the page I don't care if it's using an entry team right or if we're using jQuery or whatever you want to use like that's an implementation detail right what I'm mostly concerned about is like I want to be able to define buttons and I want them to look the same across the board so and then additionally from a performance standpoint the most expensive thing that you can do in a web browser is right to the Dom I can create 10,000 JavaScript objects faster than I can manipulate and update styles and things like that because remember we're not just changing content your web browser has to repaint it has to do frame animations it has to load Network requests and it has to handle all of this at the same time so it's much easier just javascript is also single threaded so that means that everything happens start to finish so it's a lot easier to just generate a bunch of stuff and then say hey we wanted to update all right so thinking of HTML in the Dom we just want to get on the same page all right some super simple HTML we've seen this before I think it's helpful to think of a web page as a document and that'll be our kind of basis for going forward you can edit documents right think of a text document think of a Microsoft Word document think of a Google Doc you edit it using an 8 user interface in the browser you edit the document this is the HTML document with an API that API is the Dom we've all done something like this before get an element by ID and then change it in and in our HTML right so super super simple just want to make sure we're all on the same page to how things are working all right so let's start diving into the meat of things all right so if the goal of react on the web is to generate HTML so we have a baseline under sorry a base idea of a component and components are functions or classes that describe the UI you want to ultimately end up with and JSX or JavaScript XML is the primary way that we we write that but we also don't have to so let's take a look at an example SuperDuper simple component right if you've written any functional components at all this is very familiar to you we have our main element we have an h1 has an idea of a title and we return it so when a component runs the result doesn't react creates an instance of the component so think state think props right so it's this consonant living organism so that's a component instance the instance consumes its props it deduces state etc and returns in what's known as an element an element is a plane object describing a component or HTML tag we haven't created HTML yet at this point we haven't inserted anything into Dom it's just a description of what we want to ultimately produce so this return statement returns an entity that react internally calls an element and that looks like this it's just a plain object so there's several properties here you'll notice that this is a it correlates right back to what we were just looking at so we have main and we have an h1 h1 has an idea of title and we see that right up top our very first thing as a type of main so I'm just gonna go over the properties in order and let's start making a little sense a minute all right so the type property can be a string reference or NH sorry there can be a string reference to an HTML tag react internally and call this a Dom element or it can be a reference to a component or act to call this calls us a component element so if it's type where my component when you do import my component at the top of your javascript file that's actually what would be here a reference to that the next property is the key and this is used when you're manually creating a bunch of children so when you're mapping over an entity array or sorry an array and you're generally reading a bunch of components outside from from that that's what this is used for this is become really important just a moment so we'll dive deeper into that a little bit but just just note that this is used to uniquely identify an element among siblings we'll get more into that and what that means in a second ref is a reference to an actual Dom node so if you've ever used to create ref function or the equivalent hook that's where this value ends up for those that maybe are not super familiar with that a reference is so that you you want a reference so that you can maybe focus an input or if you have a third-party library that's writing attributes to a Dom node you'd want to access those so this is where that reference ultimately ends up we have this kind of quizzical looking type of property next this is really interesting this is actually a safety feature and it's a super super edge case but it's little things like this that make me love react and the reactor core team I just get excited when I see things like this so it's values always a symbol and if you've not used symbols before I don't really either in my day-to-day symbols you you pass innocent string or I think you can pass in anything actually and it generates a unique anonymous like hash essentially and so I think of it you can if you want an analogy it's like a UUID almost and so the idea is that this is unique to the react app in it of itself what's important to note is symbols you can't have them in JSON so remember JSON ends up as a string and this is a live living object it's an entity within JavaScript so when you object type of it'll tell you it's an object or if you do a type of on a string it'll tell you to string right so symbol will come back with this a type of a symbol JSON does not the port symbol so you can't transmit them back and forth like through API calls and so this is a protection against cross great cross-site scripting attacks so like let's say that you have a like a compromised server that you're that you're making an IP API request to to get some data back if this is happening yes I know that you probably have a whole other host of issues that you need to deal with it like let's just say that's what the issue is and you get back some data and you're trying to insert that using your your component react will actually just straight up reject that because every single element that gets created it expects to have this type of property and it expects to have it that value of symbol with the reactor element passed inside of it so if if you get that back from an API response just straight up projects won't even render it so it's again super super edge case but it's a it's a nice safety feature somebody this happened to somebody and the rack core team is like oh this is a really easy this us nothing to generate a symbol like there's no performance like hindrance from this yeah so not that's not a thing that to encounter every day but I thought it was super interesting all right but then the meet the meet up the of an element is the props and so this is everything that you are accustomed to when you're creating a component in our case we only had one prop and it'll flip back just for reference so it's just a rich one so it's just an object and it's type is h1 we didn't have a key we didn't have a ref but it had props of ID which was titled and it's children was a texturing of look ma children can be an object or it can be or it can be an array so if you have multiple children it'll be an array of those objects so what react does is that builds up a whole tree of these from every component so this is what the render a render function will ultimately return back to you or the returns from a functional component it's kind of a quick review we have our component internally rectorate opponent instant state and then that ultimately generates this object this object and it's children so going all the way down is what's known as a virtual Dom and this is the kind of the core guiding principle behind why we want something like react so remember earlier when I said that it was really expensive to write to the Dom it's really cheap to generate these objects react can just do them super fast or insert view angular they have their different ways of doing it but the idea is that this is a very very fast process so we can iterate really quickly it's super cheap to build these up and tear them down which is why we want something like this over just writing to the Dom every single time we have a change all right if you'd like to see an example of an element on your own this is something you can go write in an index file right now maybe if you have a b IX j s you just defined a component notice that I have not made a function this is just the JSX itself and then you can log it you'll actually get everything that I just showed you you'll actually see some internal properties over here there's but just note that those are prepended with underscores and those are for eternal use in a internal API you so you're not supposed to use those what I also wanted to point out is that it's not there's nothing wrong with you generating this if that's how you wanted to create your react components this is totally valid you can ship this like this is a thing that you can put inside your app in a little run not not really what we're going for right like this is not expressive this is not maintainable this is very difficult to parse that's why JSX exists in the first place but yeah this is I tried it when I was like building this talk of like huh you know pretty cool all right one of the thing I wanted to chat about real quick shadow Dom this is a thing that I get asked about a lot in regards to this they're not related so the shadow Dom is a browser technology designed for scoping variables and CSS and web components that's it not really just a virtual Dom right so next in the list we have reconciliation creating the virtual Dom is part of the process known as reconciliation reconciliation is responsible for maintaining the tree of elements when a components prompts or state change so remember rad creates a tree of elements every time the render function is called that's ultimately what we're getting back so to be efficient we need to tell a way we need a way to tell what's different between the two trees so that we're only changing things in the Dom that need to be changed react our sorry reconciliation houses the diffing algorithm that determines what parts of that tree need to be replaced so let's take a look at some of that there's some examples let's say that we have two components the user is viewing a list of products or we're looking at a list of products and then maybe we tap or click on one to see an individual product what's actually happening internally so remember we have our treat right so we had wrapper and then we have product list and that's what we ended up with when whenever the root of elements have different types there's down the whole tree and it builds a whole new tree from scratch and the reason for that is their type has changed so if I flip back over to take a look at our element if that type changes so if Maine were to become say everything beneath it gets blown away and the reason for that is that if the type is changing we we're not going we're sorry so let's Becca we are we're building reusable components right so if we have a product list and then we're changing to view an individual product they're not the same thing so Rach can just make the assumption hey calculating props in state I'm going to check this out the window and just this new thing so when tearing down a tree all Dom nodes are destroyed right so this does end up generating HTML which we'll get to more on how that actual process works in a second the old Dom nodes are destroyed component instances will receive component will on mount and the equivalent use effect hook will fire so when we start building up the new tree so all the the new components are now there and we're gonna start rendering again the new Dom node it's dominoes are inserted to the DOM and then components in receive component will mount and then component did mount and then functional components will you have their use of use effect hooks run as appropriately any state associated with the old tree is lost so breaking that down a little bit react isn't reusing Dom elements it's actually destroying them and recreating them every time an element gets generated so there's some stuff happening some magical glue happening in the middle but you can think of having an element correlating directly to a Dom node so if that element changes the Dom node changes if that element goes away the Dom node goes away and there's there's some more what happens if they get moved around or what happens if some properties change like how does react know which one is which we'll get to that in a moment I just want to spend a little time kind of focusing on there are some actual under-the-hood differences as to what happens between just native HTML elements and then component in sorry so native Dom element excuse me and component elements or that reaction makes a distinction between those two types of elements so in case the class name is changing when finally rendered react finds the Dom node and just modifies the class name no need to change everything anything else because it's all the same and then a reactor will recurse on any children in our case when we hate we don't this is not semantic don't write this code alright so using a component instance let's say we're viewing an individual product maybe I'm looking at some shoes I found a sweet deal on something but then I saw at the bottom on those related products I'm like I want that was instead never a full price that's fine under the hood though what's really happening right we made an API call we got our newer sites or really it's like oh I'm gonna click on this and the ID changes so that's really the prop that would end up changing at like it had a higher level so when a component element updates the instance stays the same it is maintained a cross render so we still have the same opponent instance so remember component component instance element that component instance is staying the same so active updates the prop of the underlying component instance to match this new element we're gonna generate so then the render method is called the diff the diff algorithm recursive on the previous result and the new result comparing previous to current previous to current until the end of the tree or there's nothing left to do or nothing left to change rather alright so remember how earlier how we mentioned that elements have that key attribute and that it's useful for differentiating between children let's take a look at that alright so in this list I just have a simple unordered list with two list items and then let's say I add an item to the end it becomes this so rack compares the previous first item in the list to the next first item sees that they're the same so it says first first alright these are the same then it's a second second cool these are the same and then it's like Oh doesn't have a third new has a third I'll insert a third item it's pretty straightforward right there's nothing more complicated to it than that alright another list mr. movies well movie and show I guess what happens if we add one to the beginning instead of the end well as it stands rack doesn't know that these are different things I know that you know that to react it just says it doesn't sorry so react doesn't know that we added one to the beginning it just sees that Star Wars changed to Spaceballs so it's like cool generate a new element generate a new Dom node rewrite this yet destroy the old Dom no to regenerate a new one Star Trek has changed to Star Wars cool make the to updates and then it sees hi it's sweet I got a new one I'm gonna add it to the bottom not a super big deal in a small list like this but you can see if maybe we have some kind of WebSocket going on and we're doing like a live polling of data this can get really expensive if you have a thousand or two thousand things in a list so if you're doing a change every second this kind of operation is where something can get really really expensive and bogged down performance it's super wasteful to recreate everything every time so instead what we can do is that Keys a little bit of bias here you can see by adding keys we're able to indicate to react which elements are still the same so that as few Dom manipulations can occur as possible you're here that I keep bringing up Dom manipulations that's that's like that is ultimately what the goal of react was designed to solve right is so that weird we're touching the Dom as little as possible and so that we're able to express this in like a very very simple way so let's take a look at what happens if we add one or prepend one to the beginning of the list what happens is that react looks at the keys and it sees that hey first key is actual best this other one has a key of best it's like let me hang on a look at the second one and it sees that if I go through the difficulty of them and sorry so if I go down the list and I see that the keys are the same it actually knows oh the only thing that's actually changed is this prepending and so it just inserts it at the beginning so again going back to the example if if like we have some like live polling data that we're doing and we're like rapidly pulling and maybe we're adding one a second that's that's a very simple change in a list of a thousand or even 10,000 right we're just one one one one that's really easy the user has no ill ill performance the browser doesn't get bogged down there's no painting happening no restyling happening it's just that one element that's changing so this is what code would look like that of right right so you're mapping over an item so if we have a product list and we want to render it out this is typically what that looks like this is an example of what not to do so you'll notice the key is equal to index here that you've read this before but the explanation that I've always found online aren't always clear concise the reason is that the index can change so if I am viewing an alphabetical list so A to Z and I invert that the bottom is now at the top right well racks going to compare keys and they may or may not have changed that this is the worst world where you want where it'll look and see the old key is exactly new st. to the new key and then it won't rerender or in the case of like a completely new array it'll just rerender everything even though that the elements are largely the same so we can solve this by sum using something unique so if react sees that we're sorry' so we're using an ID and if I shift this from being top to bottom react just moves those Dom elements it just literally will invert the list for us if you don't have a unique identifier in your data maybe it's something that the user has generated so a server didn't give you a list of ID's back with this but it's okay there's a load of tool different tools that you can use my favorite to use is from load - you don't have to import the whole library even you can just import the unique identifier um and it will just literally give a unique ID and keep it so throughout the life line of your app you can also use UUID as if you want to it's a little more expensive and I don't recommend that but there are tools to do this I kind of make this a rule on my team that we always do this even if the list doesn't change even if we're not going to sort it even if there's only five items in the list right now you don't want to from it's a way future-proofing or defensive coding so it's like if I if I just go ahead and use this unique identifier in my item right now if I suddenly one day have 10,000 items in a list I don't never have to think about this again it's just automatically going to be more performance than if I'd done it the other way so huge call-out this is a likely a source of bugs that people have that they don't even realize are happening but more importantly what I want to point out is that the diffing algorithm is able to do switching of elements amongst children this doesn't happen if you shift children and what I mean is let's say that we had another unordered list here then we moved a child to be like a child's child if that makes sense react isn't going to pay attention that the key shift moved downward it's only going to be amongst children so you can't move parent to child kind of that relationship that's just going to be considered a new element also note the keys are they are just strings so you can have spaces you can so it doesn't really matter react is literally just doing strict comparison they just have to be the same that's all that matters for consistency I usually recommend not not doing something like this but most of us are probably going to end up using an ID because we're probably dealing with data from a server so anyways just pointing out edge cases and stuff like that great all right and then finally not finally well mostly finally we'll get to rendering alright so we have a pretty decent understanding of the virtual Dom so just kind of walking back through things so we have a component we get a component instance it generates an element and then ends up in the Dom somehow that's we're going to talk about next it's a little anti-climatic this this function that we write one time or create react app generated for you at the beginning of your project is is how this happens the render function off react Dom is responsible for kicking off the reconciliation process so it does the whole generate the virtual Dom generate that tree of elements and actually insert it into the Dom I want to point out that react Dom is does not come from the react library and the reason for that is that reacts job is to just do the dipping that's all that its responsible for it it doesn't actually know that you're generating HTML and this is how react and react native work react and react Dom used to be bundled in one library they used to be one and I think it was in version 13 or 14 that they split out I might have been a little earlier than that so in theory react is compatible with any kind of Dom insertion tool that you want to generate I think I saw one for blackberry sometime ago I tried to find it for a link for this talk but I couldn't so I guess it I guess it died but it was like the fact that it existed at all I was like this is really cool someone figured out how to get this to build BlackBerry apps so again the whole the whole point of the react library or the whatsapp like the crux of it is that diffing is that diffing process and the expression process for you the developer so that you don't have to think about what's actually happening under the hood this is an example of what it looks like to kick off a react native rendering process a little bit different syntax but largely the same you just have to register component for the mobile application and then your app essentially is passed in as a function the actual rendering process is done through react fiber and this is a bit of a magical mystical thing our fiber is also pretty is pretty new it came out in the past year the the promise of fiber is it gives us non-blocking renders it allows us to pause work restart work or just straight up say I don't want this anymore an example of that is think of like maybe you have a use effect or on your component did mount you have a series of AG API calls that you're making fiber actually allows the whole component to just say stop right in the middle of that process don't care anymore if you've used suspense at all there's it's not really production ready or there's the usefulness of that has not come out yet fiber is really what power is that so what's actually happening under the hood is that when you have you we have an element and then we have our domnode the fiber is what sits between and actually does those insertions for us actually getting into like does right react using like right inner HTML that's something I actually still don't know the answer to I actually did like quite a bit of pouring through the actual react library um it's very complicated it makes a lot of sense they used to not quite be this way actually so I didn't even really truly understand the power of what fiber is about to bring us until I started researching this talk there's a lot of really cool things that are about to come out because of this our applications are about to get way way cooler I think it's also maybe a little more complicated you can do some really interesting things like dynamic imports meaning that you can wait until you actually need a component before it even gets imported what this this has this has effects for very large applications where maybe you have thousands of components and why do I need them all like available why can't I just say if the user clicks that weird modal thing that nobody really access it's like Bloods of component then that's a kind of thing that should be able to do and but as far as the talk today the idea is that we have that element we have a Dom node and a fibers what handles that writing process for us all right and so with that you have a pretty understanding of how react starts with component and ends with HTML I'll review that just one more time so we end up with a component dopey bro we get a component instance it deduces state it takes props it computes them and then it generates us a tree of elements that tree of elements is our virtual DOM and then with that that's handed that started through the reconciliation process it's handed off to the rendering process and either react Dom or the component registration process for reactant native takes that and actually generates the Dom nodes or the internal view components for a react native app that are the views that the user sees and that's my talk if you want to find me on Twitter I'm at call me Tuan I tweet about JavaScript and cats thanks guys you
Info
Channel: CrossComm, Inc.
Views: 78,339
Rating: 4.9419489 out of 5
Keywords: React, Virtual DOM, UI, JavaScript, JS
Id: i793Qm6kv3U
Channel Id: undefined
Length: 29min 7sec (1747 seconds)
Published: Tue Nov 05 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.