React - Virtual DOM, Reconciliation, Fiber
Fatima Alam
Posted on April 23, 2024
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 :
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.
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.
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).
Layout Render Tree :
Browser calculates the geometry of all elements (sizes & positioning) and accordingly starts placing them.
_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.
Reconciliation
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.
Fiber
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 :
- Pause work and come back to it later
- Assign priority to different types of work
- Reuse previously completed work
- Abort work if it’s no longer needed
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.
Let’s see how all of this fits together :
- 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.
- The WIP Tree is built using fiber and the Tree’s structure matches with the structure of the Components in our code.
- 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.
- 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.
- After swapping, the new Work In Progress Tree can be used for any new future state changes.
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. 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:
- Two elements of different types will produce different trees. It does not try to diff them and simply replace the old tree.
- The developer can hint at which child elements may be stable across different renders with a key prop. React Fiber Usages :
- Error Boundaries
- Fragments
- Portals
Posted on April 23, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.