How Rendering Works: The Render Phase | Lecture 124 | React.JS 🔥
Summary
TLDRThis lecture delves into the intricate workings of React's rendering process, unveiling the mechanics behind the scenes. While initially seeming daunting, it promises a fascinating exploration for the curious mind. The virtual DOM, a JavaScript object representation, is demystified, and the reconciliation process is unveiled as the heart of React's efficiency. The Fiber reconciler, with its mutable Fiber tree and asynchronous rendering capabilities, takes center stage. Through practical examples, the script illustrates how React determines what to update, reuse, or remove from the DOM, culminating in a list of effects to be applied during the commit phase.
Takeaways
- 😃 The lecture covers the complex and fascinating topic of how React performs rendering, which is essential to understanding React's inner workings.
- 🤔 React does not actually discard and replace the entire component view or DOM during re-renders, contrary to initial explanations.
- 🌳 The virtual DOM is a tree of React elements representing the entire component tree, which is relatively cheap and fast to create.
- 🔄 When a component is re-rendered, all of its child components are also re-rendered, regardless of whether their props have changed or not.
- ⚡ React uses a process called reconciliation to efficiently update the DOM by reusing as much of the existing DOM tree as possible.
- 🧠 The reconciler, called Fiber, is the engine of React and allows updates without directly touching the DOM.
- 🌲 The Fiber tree is a mutable data structure that keeps track of component state, props, effects, and more, and is mutated during reconciliation.
- ⏱️ Fiber can perform work asynchronously, enabling features like Suspense and improving performance by not blocking the JavaScript engine.
- 🔍 Reconciliation involves diffing, which compares elements step-by-step based on their position in the tree to determine necessary DOM mutations.
- 📜 The final result of the render phase is an updated Fiber tree and a list of effects (DOM operations) to be executed in the commit phase.
Q & A
What is the purpose of this lecture?
-The lecture aims to explain the inner workings of the rendering process in React, specifically focusing on the render phase and how reconciliation is performed.
What is the virtual DOM in React?
-The virtual DOM, also known as the React element tree, is a tree of all React elements created from all instances in the component tree. It is a JavaScript object representation of the UI, relatively cheap and fast to create.
Why does React re-render child components when a parent component is updated?
-React re-renders child components of an updated component because it doesn't know beforehand whether the update in the parent component will affect the child components or not. By default, React prefers to play it safe and re-render everything.
What is the purpose of reconciliation in React?
-Reconciliation is the process of deciding which DOM elements need to be inserted, deleted, or updated in order to reflect the latest state changes. It allows React to efficiently update the DOM by reusing as much of the existing DOM tree as possible.
What is the Fiber reconciler in React?
-The Fiber reconciler, also known as just 'Fiber,' is the engine of React. It is responsible for performing the reconciliation process and building the Fiber tree, which is an internal tree representing the component instances and DOM elements in the application.
What is the Fiber tree in React?
-The Fiber tree is a special internal tree where, for each component instance and DOM element in the app, there is one so-called 'Fiber.' Fibers are mutable data structures that keep track of things like component state, props, side effects, and hooks. The Fiber tree is never destroyed, but rather mutated during reconciliation.
How does the Fiber reconciler handle asynchronous rendering?
-The Fiber reconciler can perform work asynchronously, splitting the rendering process into chunks, prioritizing tasks, and pausing or resuming work as needed. This allows rendering to pause and resume later, preventing it from blocking the browser's JavaScript engine with long renders.
What is the 'diffing' process in React's reconciliation?
-Diffing is the process of comparing elements step-by-step, based on their position in the tree, to analyze what needs to change between the current Fiber tree and the updated Fiber tree based on the new virtual DOM.
What is the 'list of effects' in React's rendering process?
-The list of effects is a list of DOM mutations (insertions, deletions, or updates) that need to be performed, which is the result of the reconciliation process. This list will be used in the commit phase to actually mutate the DOM.
What is the next phase after the render phase in React's rendering process?
-The next phase after the render phase is the commit phase, where React uses the list of effects generated during the render phase to actually mutate the DOM and apply the changes to the UI.
Outlines
🧩 The Complexity and Curiosity of React's Rendering Process
This paragraph introduces the complex and confusing nature of React's rendering process, but also highlights its fascinating and interesting aspects. It encourages viewers to approach the topic with an open mind, as understanding the inner workings of React is not essential for using it. The paragraph then revisits the concept of state mechanics and rendering introduced earlier, clarifying that previous explanations were not entirely accurate. It sets the stage for exploring the actual rendering process in this lecture.
🔄 Triggering Re-renders and the Virtual DOM
This paragraph discusses how re-renders are triggered in React. It explains that during the render phase, React goes through the entire component tree, renders the components that triggered a re-render, and creates an updated virtual DOM (a tree of React elements). The virtual DOM is described as a relatively cheap and fast object representation of the component tree, but the term has been downplayed by the React team in recent documentation. The paragraph then introduces the concept of state updates triggering re-renders and the creation of a new virtual DOM.
⚡️ The Reconciliation Process and Fiber Architecture
This paragraph introduces the reconciliation process, where the new virtual DOM is reconciled with the current Fiber tree (a mutable data structure representing the component tree). It explains that the reconciliation process results in an updated Fiber tree, which will eventually be used to update the DOM. The paragraph also discusses the Fiber reconciler and its ability to perform work asynchronously, enabling features like Suspense and transitions in React 18. The Fiber tree is described as a linked list data structure that stores component state, props, and side effects.
🔍 Diffing and DOM Mutations in the Reconciliation Process
This paragraph dives into the reconciliation process using a practical example. It explains how the Fiber reconciler walks through the entire tree, analyzing what needs to change between the current Fiber tree and the updated Fiber tree based on the new virtual DOM. This process of comparing elements step-by-step based on their position in the tree is called diffing. The paragraph then analyzes the updated Fiber tree, highlighting the different types of work (DOM updates, deletions, and unchanged elements) that need to be performed. Finally, it mentions that these DOM mutations will be placed into a list of effects, which will be used in the next phase (the commit phase) to actually mutate the DOM.
Mindmap
Keywords
💡Rendering
💡Virtual DOM
💡Reconciliation
💡Fiber
💡Fiber Tree
💡Asynchronous Rendering
💡Diffing
💡List of Effects
💡Commit Phase
💡State
Highlights
React creates a virtual DOM, which is a JavaScript object tree representing the user interface, to enable efficient updates and reconciliation processes.
When a component is re-rendered, all of its child components are re-rendered as well, regardless of whether their props have changed or not.
React reconciles the new virtual DOM with the current Fiber tree, which is an internal mutable data structure representing the component instances and DOM elements.
The reconciliation process, performed by the Fiber reconciler, determines the necessary DOM operations to update the current DOM with the new state.
The Fiber tree is a special internal tree where each component instance and DOM element has a corresponding Fiber, which stores state, props, side effects, and a queue of work to be done.
The Fiber reconciler can perform work asynchronously, splitting the rendering process into chunks, prioritizing tasks, and pausing or resuming work as needed.
The reconciliation process involves diffing, which compares elements step-by-step based on their position in the tree to determine what needs to change between the current Fiber tree and the updated Fiber tree.
The result of the reconciliation process is a list of DOM operations (effects) that need to be performed in the commit phase to update the actual DOM.
React does not update the entire DOM; it reuses as much of the existing DOM tree as possible and only updates the necessary parts based on the reconciliation process.
The virtual DOM and reconciliation process allow React to efficiently update the user interface without directly touching the DOM, which is an expensive operation.
The Fiber tree is arranged in a linked list structure, with each child Fiber having a link to its parent and siblings, making it easier for React to process the associated work.
The asynchronous rendering enabled by the Fiber reconciler allows modern concurrent features like Suspense and transitions, and prevents blocking the browser's JavaScript engine with long renders.
The reconciliation process involves walking through the entire tree and analyzing exactly what needs to change between the current Fiber tree and the updated Fiber tree based on the new virtual DOM.
The term 'virtual DOM' is a commonly used term, even though the React team has downplayed its meaning, and the official documentation no longer mentions it.
The reconciliation process is performed by the Fiber reconciler, which is considered the engine or heart of React, allowing developers to never touch the DOM directly.
Transcripts
Welcome back to probably the most complicated
and most confusing lecture of the entire course.
But I don't say this to scare you
because this might also be the most interesting
and fascinating lecture of the course.
Now, if you don't immediately understand 100%
of what I'm gonna teach you here, that's absolutely fine.
So don't stress about it at all.
Again, you can use React without knowing any of this stuff
but if you have a curious mind
and feel the need to understand how React does what it does,
then this video is for you.
Now, before we even start, let's first go back
to where we first learned about the mechanics of state.
Remember this diagram?
Well, back then I told you
that we can conceptually imagine this
as a new view being rendered on the screen, so into the DOM.
However, now we know that this was technically not true
because rendering is not about the screen or the DOM
or the view, it's just about calling component functions.
I also told you that whenever there is a re-render,
React discards the old component view
and replaces it with a brand new one.
However, that's also technically not true.
So the DOM will actually not be updated
for the entire component instance.
So if those things are not true, then let's now learn
what happens instead and how rendering actually works.
So, in the previous lecture we talked
about how renders are triggered.
In this lecture, we're gonna learn all about
how renders are actually performed in the render phase.
So, at the beginning of the render phase
React will go through the entire component tree,
take all the component instances that triggered a re-render
and actually render them, which simply means
to call the corresponding component functions
that we have written in our code.
This will create updated React elements
which altogether make up the so-called virtual DOM.
And this is a term that you might have heard before
and so let's dig a little bit deeper now
into what the virtual DOM actually is.
So on the initial render, React will
take the entire component tree and transform it
into one big React element which will
basically be a React element tree like this one.
And this is what we call the virtual DOM.
So, the virtual DOM is just a tree
of all React elements created
from all instances in the component tree.
And it's relatively cheap and fast to create a tree
like this, even if we need many iterations of it
because in the end it's just a JavaScript object.
Now, virtual DOM is probably the most hyped
and most used term when people describe
what React is and how it works.
But if we think about it, if the virtual DOM
is just the simple object,
it's actually not such a big deal, right?
And that's why the React team has really
downplayed the meaning of this name.
And the official documentation actually no longer
mentioned the term virtual DOM anywhere.
But I'm still using this term here
because everyone still uses it and also
because it just sounds a bit nicer than React element tree.
Also, some people confuse the term with the shadow DOM,
even though it has nothing to do
with the virtual DOM in React.
So the shadow DOM is actually just a browser technology
that is used in stuff like web components.
But anyway, let's now suppose
that there is gonna be a state update in component D,
which will of course trigger a re-render.
That means that React will call the function
of component D again and place the new React element
in a new React element tree.
So, in a new virtual DOM.
But now comes the very important part, which is this.
Whenever React renders a component,
that render will cause all of its child components
to be rendered as well.
And that happens no matter if the props
that we passed down have changed or not.
So again, if the updated components
returns one or more other components,
those nested components will be re-rendered as well,
all the way down the component tree.
This means that if you update the highest component
in a component tree, in this example component A,
then the entire application will actually be re-rendered.
Now, this may sound crazy, but React uses this strategy
because it doesn't know beforehand whether an update
in a component will affect the child components or not.
And so by default, React prefers to play it safe
and just render everything.
Also, keep in mind once again that this does not mean
that the entire DOM is updated.
It's just a virtual DOM that will be recreated
which is really not a big problem
in small or medium sized applications.
Okay, so with this, we now know what
this new virtual DOM here means
and so let's keep moving forward.
So what happens next is that
this new virtual DOM that was created
after the state update will get reconciled
with the current so-called Fiber tree
as it exists before the state update.
Now this reconciliation is done in React's reconciler
which is called Fiber.
Now that's why we have a Fiber tree.
Then the results of this reconciliation process
is gonna be an updated Fiber tree,
so a tree that will eventually be used to write to the DOM.
So this is a high level overview
of the inputs and the outputs of reconciliation,
but, of course, now we need to understand
what reconciliation is and how it works.
So, you might be wondering why do we even need stuff
like the virtual DOM, a reconciler and those Fiber trees?
Why not simply update the entire DOM
whenever state changes somewhere in the app?
Well, the answer is simple.
Remember how we said that creating the virtual DOM
so the React element tree for the entire app is cheap
and fast because it's just a JavaScript object?
Well, writing to the DOM is not cheap and fast.
It would be extremely inefficient
and wasteful to always write the entire virtual DOM
to the actual DOM each time that a render was triggered.
Also, usually when the state changes somewhere in the app
only a small portion of the DOM needs
to be updated and the rest of the DOM
that is already present can be reused.
Now, of course, on the initial render
there is no way around creating the entire DOM from scratch
but from there on, doing so doesn't make sense anymore.
So imagine that you have a complex app like udemy.com
and when you click on some button there
then showModal is set to true,
which in turn will then trigger a modal to be shown.
So in this situation, only the DOM elements
for that modal need to be inserted into the DOM
and the rest of the DOM should just stay the same.
And so that's what React tries to do.
Whenever a render is triggered,
React will try to be as efficient as possible
by reusing as much of the existing DOM tree as possible.
But that leads us to the next question.
So how does React actually do that?
How does it know what changed
from one render to the next one?
Well, that's where a process
called reconciliation comes into play.
So reconciliation is basically deciding exactly
which DOM elements need to be inserted, deleted
or updated in order to reflect the latest state changes.
So the result of the reconciliation process
is gonna be a list of DOM operations that are necessary
to update the current DOM with a new state.
Now, reconciliation is processed by a reconciler
and we can say that the reconciler
really is the engine of React.
It's like the heart of React.
So it's this reconciler that allows us
to never touch the DOM directly
and instead simply tell React what the next snapshot
of the UI should look like based on state.
And as I mentioned before, the current reconciler
in React is called Fiber, and this is how it works.
So, during the initial render of the application
Fiber takes the entire React element tree,
so the virtual DOM, and based on it
builds yet another tree which is the Fiber tree.
The Fiber tree is a special internal tree where
for each component instance and DOM element in the app,
there is one so-called Fiber.
Now, what's special about this tree
is that unlike React elements in the virtual DOM,
Fibers are not recreated on every render.
So the Fiber tree is never destroyed.
Instead, it's a mutable data structure
and once it has been created during the initial render,
it's simply mutated over and over again
in future reconciliation steps.
And this makes Fibers the perfect place for keeping track
of things like the current component state, props,
side effects, list of used hooks and more.
So the actual state and props of any component instance
that we see on the screen are internally stored
inside the corresponding Fiber in the Fiber tree.
Now, each Fiber also contains a queue of work to do
like updating state, updating refs,
running registered side effects,
performing DOM updates and so on.
This is why a Fiber is also defined as a unit of work.
Now, if we take a quick look at the Fiber tree
we will see that the Fibers are arranged in a different way
than the elements in the React element tree.
So instead of a normal parent-child relationship,
each first child has a link to its parent
and all the other children then have a link
to their previous sibling.
And this kind of structure is called a linked list
and it makes it easier for React to process the work
that is associated with each Fiber.
We also see that both trees include not only React elements
or components, but also regular DOM elements,
such as the h3 and button elements in this example.
So both trees really are a complete representation
of the entire DOM structure, not just of React components.
Now going back to the idea that Fibers are units of work,
one extremely important characteristic
of the Fiber reconciler is that work
can be performed asynchronously.
This means that the rendering process
which is what the reconciler does, can be split into chunks,
some tasks can be prioritized over others
and work can be paused, reused,
or thrown away if not valid anymore.
Just keep in mind
that all this happens automatically behind the scenes.
It's completely invisible to us developers.
There are, however, also some practical uses
of this asynchronous rendering
because it enables modern so-called concurrent features
like Suspense or transitions starting in React 18.
It also allows the rendering process
to pause and resume later so that
it won't block the browser's JavaScript engine
with two long renders, which can be problematic
for performance in large applications.
And again, this is only possible
because the render phase does not produce
any visible output to the DOM yet.
Okay, so at this point we know
what the Fiber reconciler is and how the Fiber tree works
but now it's time to talk about what Fiber actually does
which is the reconciliation process.
And the best way to explain how reconciliation works
is by using a practical example.
So let's take the virtual DOM
and the corresponding Fiber tree from the last slide
which corresponds to this piece of code right here.
So in the app component, there is a piece
of state called showModal, which is currently set to true
and you can pause the video here to analyze it
but it's not really necessary.
So let's say now that the state is updated to false.
This will then trigger a re-render
which will create a new virtual DOM.
And in this tree, the modal
and all its children are actually gone
because they are no longer displayed
when showModal is not true.
Also, all remaining React elements are yellow,
meaning that all of them were re-rendered.
And do you remember why that is?
That's right.
It's because all children of a re-rendered element
are re-rendered as well,
as we just learned a few minutes ago.
But anyway, this new virtual DOM now needs
to be reconciled with the current Fiber tree,
which will then result in this updated tree
which internally is called the work in progress tree.
So whenever reconciliation needs to happen,
Fiber walks through the entire tree step by step
and analyzes exactly what needs to change
between the current Fiber tree
and the updated Fiber tree based on the new virtual DOM.
And this process of comparing elements step-by-step
based on their position in the tree is called diffing
and we will explore exactly how diffing works
a bit later in the section
because that's actually pretty important in practice.
But anyway, let's quickly analyze our updated Fiber tree
where I marked new work that is related to DOM mutations.
So first, the Btn component has some new text
and so the work that will need to be done
in this Fiber is a DOM update.
So in this case, swapping text from height to rate.
Then we have the Modal, Overlay, h3 and button.
So these were in the current Fiber tree
but are no longer in the virtual DOM
and therefore they are marked as DOM deletions.
Finally, we have the interesting case
of the video component.
So this component was re-rendered because it's a child
of the app component, but it actually didn't change.
And so as a result of reconciliation,
the DOM will not be updated in this case.
Now, once this process is over, all these DOM mutations
will be placed into a list called the list of effects
which will be used in the next phase,
so in a commit phase, to actually mutate the DOM.
Now, what I showed you here was actually still
a bit oversimplified, if you can believe that,
but I think that this is more than enough
for you to understand how this process works.
Okay, so that was quite a deep dive, but now we're back here
in the high level overview of the render phase.
So we learned that the results of the reconciliation process
is a second updated Fiber tree, plus basically a list
of DOM updates that need to be performed in the next phase.
So React still hasn't written anything to the DOM yet
but it has figured out this so-called list of effects.
So this is the final result of the render phase
as it includes the DOM operations that will finally be made
in the commit phase, which is the topic of our next video.
So if you don't want to break the flow,
then let's move on there right now.
Ver Más Videos Relacionados
How Rendering Works: Overview | Lecture 123 | React.JS 🔥
How Events Work in React | Lecture 134 | React.JS 🔥
State Update Batching | Lecture 132 | React.JS 🔥
Course Introduction | Mastering React: An In-Depth Zero to Hero Video Series
Q. What are the Key Features of React ?
React tutorial for beginners ⚛️
5.0 / 5 (0 votes)