So, how does React actually work? We all know we can create React components
using JSX and then render them on the web using React DOM or in a mobile app using React
Native. We also have access to incredible features
like the state or the component lifecycle and finally it is all extremely fast and flexible,
but what is actually happening behind the scenes? In this video, we will go over the basic concepts
that make React what it is. We will focus on reconciliation and rendering,
the virtual DOM, the React Diffing algorithm and much more. So, let’s get to it. First, we have to understand the difference
between React components, elements and component instances. Let’s start by taking a look at a simple
component. I think this should be very familiar to you. For us, it is a React component that returns
some React elements using JSX, the JavaScript XML. But for React, the return value is an object
that looks like this. If you want to check for yourself, you can
just log it to the console. When we call the component, we get the real
return value. So, what exactly is happening? First, the JSX gets converted to many React.createElement
function calls. Then, each of them returns the appropriate
object. The fact that JSX gets converted to the React.createElement
functions is the reason why we always have to import React when using JSX. Now, let’s take a close look at the return
value. In our case, it is object that represents
the root element, a div. The div is a type property, which corresponds
to an HTML element. We can also see the key and ref properties,
which are both null, because we haven’t provided any of them. There are also the familiar props and they
contain all of the children. In our case, it is a simple text of “App
component”. I previously mentioned a function called React.createElement
and you might wonder how does it look like in practice. Well, let’s just head over to babeljs.io/repl
and here, I will pass in the App component. Then, on the right side, we can see the converted
code. We can see the React.createElement function
being called with some arguments. The first argument is the element type, the
second one are the props and the third argument are the children. Now, just so we are sure how it works, let’s
take a look at a slightly more complicated component. We can once again see the type div, but the
props are a bit more interesting. They contain a className of “App” and
two children. The first is an image with source and className
props and the second is a heading with the text of “App component”. By now, you might already have a few questions. First, why isn’t the key and the ref part
of the props? Well, they are special properties and we will
examine them further in the video. Second, what in the world is the $$typeof
property? Well, it is just a security measure and if
you want to learn more, there is a link in the description to an article about it. Now, we should have a good understanding of
what a React element is. So, what is a React component? Well, a React component is a class or a function
that outputs an element tree. If it is a function, the output is the return
value of the function, and if it is a class, the output is the return value of the render
method. Not only do React components have an output,
they also have an input, which we all are familiar with – the props. All of this might seem very easy and obvious
to you, but this is where it gets tricky. Just before a while, I showed you what the
output is when we call a component. But we don’t really call them in our code,
do we? We just add them to the JSX like this. So, what is the output of this? Let’s once again check that using console.log
Well, it looks like a React element, but it is kind of weird. The type is some sort of a function and well,
that is actually our component. When we render our component in the JSX, React
is in fact calling it behind the scenes. If it is a function, React calls it directly
with the assigned props and if it is a class, React creates a new instance of the class
and calls its render method. So not only can React elements describe a
DOM node, they can also describe a component, more precisely a component instance. But what is a component instance? When a React element describes a component,
React keeps track of it and creates a component instance. Each instance has state and lifecycle and
those instances are in fact very familiar to us. In functional components, we can access the
state and the lifecycle using React Hooks and in class components, we make use of predefined
methods and the “this” keyword, which refers to the individual component instance. The same way React calls our components, it
also manages our instances by mounting and unmounting them. So now, we should have a pretty good knowledge
of React elements, components and component instances. Now, it’s time to move to reconciliation. We know that all React does is create a tree
of elements. This process is extremely fast, because as
we saw, elements are just plain JavaScript objects and we can basically create thousands
of objects in an instant. All of this is happening, when we call the
render method. React generates this tree of elements by starting
at the very top and recursively moving to the very bottom. If it encounters a component, it calls it
and keeps descending down to the returned React elements. React keeps this tree of elements in memory,
it is called the virtual DOM. The next thing to do is to sync the virtual
DOM with the real DOM. On the initial render, React has to insert
the full tree into the DOM. Making those kinds of adjustments to the DOM
is very expensive, but on the initial render, there is no way around it. But what if the tree changes? What if there is a state change which results
into a different return value and different elements? React once again very quickly generates a
new tree of elements and we now have two trees – the old one and the new one. Now, it has to once again sync the virtual
DOM containing the new tree with the real DOM. It would be very inefficient to re-render
the whole tree, because as I said, making changes to the DOM is quite demanding. And this is why Reacts takes the old tree
and finds the smallest number of operations to transform it to the new tree. It uses an algorithm called the Diffing algorithm
in order to do that, diffing, because the goal is to differentiate the trees. Under normal circumstances, this is would
be very difficult. For example, if we had one thousand elements,
it could take up to one billion operations, which is not realistic. React instead manages to do that in a number
of operations smaller than the number of elements. So, for one thousand elements, the number
of operations will be smaller than one thousand. This is incredibly fast and it is possible
only because of two very important assumptions. Let’s talk about those now. First, it assumes that two different types
of elements will produce two completely different trees. You might be looking at this and saying “But
isn’t this obvious?” and, generally speaking, not so much, but in the context of a React
application, we can safely assume that two different element types will indeed result
in two very different trees. The second assumption is simpler. React assumes then when we have a list of
child elements, which we make changes to, we will provide the key and we will provide
it in the right way. Let’s take a look at an example. Say we have a list of items that we map over
and we have to provide unique keys. The first idea you might have is to provide
keys using indexes, but this is one of the infamous bugs that I’m sure most of us came
across at some point. This leads to unexpected functionality and
it shouldn’t be surprising at all. We know that keys should always stay the same. Therefore, if we add a new item to the list
to the very beginning, the keys will all increase by 1 which is wrong. This is why we provide keys using ids or simply
unique properties. Previously, I mentioned that you may wonder
why key isn’t part of the props. Now, you should understand why – key is
unlike any other property. It is an important part of the very core of
React – the Diffing algorithm. Now, let’s take a look at some of the basic
operations that are part of the Diffing algorithm. Let’s say we have two elements at the same
position with different types. In this case, React will just build a new
tree from scratch, because of the first assumption. This means that all component instances in
the old tree are destroyed along with their current state. We say that the components unmount. What if we have two elements at the same position
with the same type, but with different attributes? React simply updates those attributes. The instances stay the same and the state
is maintained. Let’s move to changing children. Imagine a list of names. What if we add a name to the end of the list? React first compares the first items and recognizes
that they are the same. Then, it notices that the third item is new
and just inserts it. But what if we add a name to the start of
the list? In this case, React compares the items at
same positions and notices that they are all different, so it basically generates a new
tree. But this isn’t what we want. If we have ten thousand items and add a new
one to the start, we don’t just want to generate a new tree. What we can do is provide keys. Using keys, we tell React which elements are
still the same and which are new. Once again, this is why we can’t use index
as a key. So that’s reconciliation. Now, let’s move to the rendering itself. This is where packages like React DOM and
React Native come into play. We call those packages renderers. React on its own is just a library that allows
us to define components and elements and it also does the diffing part. It isn’t platform specific and doesn’t
take care of the rendering. Most of the actual implementation lives in
the renderers. Renderers begin the reconciliation process. They generate the tree of elements and insert
it wherever it has to be inserted. This is why they are a different package. When we use React for web development, React
basically doesn’t even know that the elements end up in a web browser. React is therefore compatible with any renderer
and you can in fact create your own using the react-test-renderer package. Once again, just to emphasize, React on its
own only gives us the means of expression, so we can define components and so on, and
it also does the diffing part. When you think about this, it may appear quite
weird to you. In terms of web development, we usually only
import React DOM once and call its render method. So how can most of the implementation live
in the renderer package? The key to understanding this is to know that
React communicates with the renderer. There are many ways of React doing that, but
let’s explore one of them, the setState function. So, how exactly does setState work? setState is part of class components and the
answer is that every renderer sets a special field on the created class. This field is called updater. When we use React on the web, it is React
DOM that sets this field right after creating an instance of the class. Internally, it looks similarly to this. First, an instance of the class component
is created and afterwards, we can see that the updater field is indeed being set to something
that is part of React DOM. Then, whenever we call setState, a function
similar to this one gets called. Here, a method called enqueueSetState of the
updater field is called. Now, it should be quite clear how React communicates
with the renderers. We could talk about state and the enqueueSetState
method, but it is very complicated and is more of a topic for another video. What about React hooks? React hooks basically do the same thing, however,
instead of an updater field, they use a dispatcher object. Internally, it looks similarly to this. We can see that when we call useState, the
call is forwarded to something called currentDispatcher. And this dispatcher is once again set by React
DOM. Whenever we render a component, React DOM
sets the dispatcher similarly to this. This time around, the component is called,
because it is a function. So, this is how React communicates with the
renderers. And that’s all I wanted to talk about in
this video. We’ve learned about React elements, components,
component instances, reconciliation, rendering, the virtual DOM, the Diffing algorithm and
its two very important assumptions. We’ve also learned about the ways React
communicates with its renderers and peeked at a little bit of the internal code. There are many, many more things we could
talk about and we could in fact go into much more detail, but I don’t want this video
to be too long. My plan going forward is to create a video
about React state and also another one about React hooks, where we will explore how they
work behind the scenes. If you want to learn how to use React hooks,
I’ve just recently finished a series where I covered each of the React hooks in detail. Let me know in the comments what kind of content
would you like to see in the future. If you enjoyed the video, be sure to leave
a like and subscribe to see more videos like this in the future. Thank you very much for watching.