React Virtual DOM, Reconciliation and Fiber Reconciler

Naman Saxena
8 min readFeb 19, 2022

--

In this article, we are going to discuss React Virtual DOM and how Reconciliation works under the hood.

Introduction

Before discussing Virtual DOM, we need some context of the Browser Rendering process and DOM.

These are the steps browser follows to render our website :

  1. Parsing HTML :
    The browser parses our HTML and stores it in memory as a tree structure of a document, which is also known as DOM (Document Object Model) or sometimes as Real DOM. It is a Web API used to build websites.
    DOM methods allow programmatic access to the tree. With them, you can change the document’s structure, style, or content.
  2. Parsing CSS :
    The browser parses our CSS and stores it in memory as CSSOM (CSS Object Model). It is a Web API to manipulate the CSS of our website.
  3. Creating Render Tree :
    The browser uses DOM and CSSOM to create a render tree. Render Tree represents everything that will be rendered on the browser (HTML nodes with their styles).
  4. Layout Render Tree :
    Browser calculates the geometry of all elements (sizes & positioning) and accordingly starts placing them.
  5. Painting :
    Now it will start painting all individual nodes according to their styles.

Virtual DOM

It is the representation of DOM as a JavaScript Object. It is a concept implemented by JS Libraries & Frameworks to achieve state-driven UI development. This helps React in batching state changes and taking care of smooth state transitions.

When discussing React Virtual DOM, it is said that it helps React in re-rendering only those parts of the Browser DOM tree that needed to be updated, which is true. But the catch is, it said as if doing DOM manipulation using Vanilla JS always results in re-rendering of the whole page and that is not true.
Modern Browsers are capable enough to make changes only to updated elements using Vanilla JS.

I have made 2 simple clock projects (1 using Vanilla JS & 1 using React) to explain this point.

Vanilla JS Clock Source Code: https://github.com/Naman-Saxena1/clock-example-vanilla-js

React Clock Source Code: https://github.com/Naman-Saxena1/clock-example-react

Need of Virtual DOM

When we make any state changes in our React application, it creates a new version of the whole Virtual DOM with the latest updates. React then find elements that need to be changed by comparing the old Virtual DOM tree and updated Virtual DOM tree. And then only updates elements in Browser DOM that have changed. React uses Diffing Algorithm to compare 2 Virtual DOM trees, we will discuss that in later sections.

Real DOM and Virtual DOM

Since React creates a new UI for each state change, Virtual DOM helps React as making changes to the new Virtual DOM tree does not immediately trigger reflow and repaint because nothing is being drawn on the browser screen.

The benefit of using 2 Virtual DOM trees is 1 tree acts as a draft and is later used to do batch updates to real DOM. The old Virtual DOM tree is called Current Tree and another one is called Work in Progress Tree (because it is basically used as a draft). In Dan Abramov’s Youtube Video, he explained the motivation of 2 Virtual DOM trees came from The Double Buffering Technique that was used in the earlier days for Game Development.

So React 1st make changes to Work in Progress Tree and then it also update changes to Real DOM. So it is basically doing extra work than a website written using Vanilla JS. But it is still good enough in terms of performance.

You can read more about this :

We use React rather than Vanilla JS because it is Declarative, Offers Reusable Components and helps to easily build complex UI while abstracting away difficult parts.
Plus since modern websites like Facebook, Netflix, Dropbox, etc. are highly dynamic, using Work In Progress Tree and then batching updates is beneficial.

That is why you might have noticed, if you ever do something like the below example, setState() batches updates as it is asynchronous.

this.setState() will batch updates

You can read more about this :
https://github.com/facebook/react/issues/11527#issuecomment-360199710

Some important terminologies

To get a better understanding, we need to discuss some terminologies before discussing the whole Reconciliation process.

Reconciliation is the process of keeping 2 DOM Trees in sync by a library like ReactDOM. It is done by using Reconciler and a Renderer.

Reconciler uses Diffing Algorithm to find differences between Current Tree and Work in Progress Tree and sends computed changes to the Renderer.

The Renderer is the one that updates the app’s UI. Different devices can have different Renderers while sharing the same Reconciler.

Before React 16, React used to work on Call Stack to keep track of the program’s execution. Hence old reconciler has been given the name Stack Reconciler. The problem with this approach is that it was synchronous and if a lot of execution happens all at once. It could cause frame drops in animations and poor UI experience. It used to have only 1 Virtual DOM tree and it made some features like Suspense and Concurrent Mode impossible to implement because they rely on Reconciler’s ability to work asynchronously.

In React 16, they created a new Reconciler from scratch which uses a new data structure called fiber. Hence it is called Fiber Reconciler. The main aim was to make the reconciler asynchronous and smarter by executing work on the basis of priority.

React Fiber needs to be asynchronous by taking advantage of cooperative scheduling and should be able to do :
1. Pause work and come back to it later
2. Assign priority to different types of work
3. Reuse previously completed work
4. Abort work if it’s no longer needed

fiber is a Javascript Object which represents a unit of work. For each React Component and Element, React creates its own fiber object. It has a one-to-one relationship with an instance and manages the work for an instance. And also keeps track of its relationships to other fiber objects in the Virtual DOM tree.

Priority List: React Fiber gives different importance to different updates and executes them according to their priority.

Priority List :
0 : No Work //No work is pending
1 : SynchronousPriority //For controlled text inputs. Synchronous side effects
2 : TaskPriority //Needs to complete at the end of the current tick
3 : AnimationPriority //Needs to complete before the next frame
4 : HighPriority //Interaction that needs to complete pretty soon to feel responsive
5 : LowPriority //Data fetching, or result from updating stores
6 : OffscreenPriority //Won't be visible but do the work in case it becomes visible

Reconciliation Process

Browser’s Main thread is used for creating Work In Progress Tree with React, processing user events, repaint, etc.

During Phase 1

Let’s see how all of this fits together :

  1. When we make changes to our state, React waits for Main Thread to become idle and then starts building a Work In Progress (WIP) Tree on it.
  2. The WIP Tree is built using fiber and the Tree’s structure matches with the structure of the Components in our code.
  3. This phase (render / reconciliation phase) of building WIP Tree and figuring out changes to be made is asynchronous and can be paused if Main Thread has some other work to complete. In that case, the main thread starts working on those updates according to their priority in the Priority List. Once the Main thread is idle again, it resumes building WIP Tree where it last left it off.
  4. The second phase (commit phase) starts once the whole WIP Tree is completed, this phase is synchronous and can’t be interrupted. In this phase, React will make those changes to the DOM. It does that by swapping pointers of the Current Tree and Work In Progress Tree. And then flushing (render) those fibers to the DOM.
  5. After swapping, the new Work In Progress Tree can be used for any new future state changes.
Swapped Current Tree and Work In Progress Tree Pointers

Now that we got a higher-level understanding of how the whole Reconciliation Process is working, we can discuss some important points.

  1. During the comparison of the Current Tree and the Working In Progress Tree, React marks fibers that need to be changed. And then later create an Effect List of them, which will be later used to make changes in the DOM.
  2. Each Fiber has an alternate property that points to the Fiber in another Tree. While creating Work in Progress Tree, Reacts finds out fibers that don’t need changes and just clone them from the Current Tree. This helps React in reusing work.
  3. Diffing Algorithm is used for the above 2 steps and makes React as efficient as possible.
  4. The state-of-the-art algorithms have a complexity in the order of O(n3) where n is the number of elements in the tree. Hence, React implements a heuristic O(n) algorithm based on two assumptions:
    1. Two elements of different types will produce different trees. It does not try to diff them and simply replace the old tree.
    2. The developer can hint at which child elements may be stable across different renders with a key prop.
  5. React Fiber Usages :
    1. Error Boundaries
    2. Fragments
    3. Portals

If you are someone who wants to learn React and is looking for free good resources, I found Codevolution Youtube React Playlist extremely helpful.

Below are the resources I found useful to understand React Fiber :
1. Lin Clark React Conf 2017: https://www.youtube.com/watch?v=ZCuYPiUIONs

2. Andrew Clark Github: https://github.com/acdlite/react-fiber-architecture

3. Philip Fabianek Youtube Playlist: https://www.youtube.com/playlist?list=PLxRVWC-K96b0ktvhd16l3xA6gncuGP7gJ

4. Freecodecamp React Components & React Elements by Samer Buna : https://www.freecodecamp.org/news/react-interview-question-what-gets-rendered-in-the-browser-a-component-or-an-element-1b3eac777c85/

Hi folks!
I hope you found any of it informative or helpful. If you have any suggestions/criticism for the article, kindly comment below.

Thanks for reading!

--

--

Naman Saxena

23 | Software Engineer | Tech Enthusiast | Astrophile