Notes on React Virtual DOM
Posted on Dec 3rd 2026 / tech đťReact Fibre In Depth
Concepts: Critical rendering path -> The steps taken to convert HTML, CSS, JS to pixels on screen:
- DOM Construction -> HTML -> parsed to -> JS Objects / DOM Nodes = DOM Tree CSSOM Construction -> Styles -> CSS Object Tree
- DOM Tree + CSSOM tree -> Combined to form âRender Treeâ / âLayout Treeâ
- Layout / Reflow -> Using Render Tree, browser calculates the exact geometry of each object in the tree (position & sizes)
- Paint: Browser âpaintsâ (rasterizes) the pixels for each element onto layers.
- Compositing: If multiple layers, they are composited together to form the final image on the screen.
Notes:
-
Layer: Each element belongs to a âlayerâ (like in photoshop), and composed together they form the web page.
-
Efficiency: If only one layer changes, browser only needs to re-paint & re-composite a single layer.
-
The heuristics & algo. used by each browser can be different to determine the layers.
Concept: React Virtual DOM
Virtual DOM -> In memory lightweight representation of the real DOM composed of Javascript objects.
Actual DOM elements are, internally, C++ objects created by the browser engine. e.g. <div>, <button> etc. are represented by C++ object, and are super optimized for rendering and layout. The Javascript interface (Web API) are exposed by the browser for developers to interact with the underlying objects.
Concept: Stack Reconcilliation Algorithm
- Generate virtual DOM tree (Synchronous)
- Diffing process: React compares the new virtual DOM tree and previous VDOM tree in a depth first & synchronous manner.
- This is the main bottleneck, as imagine there are 10,000 items in a list, as this is synchronous this could block the main UI thread.
- Batching & DOM update: Once React identifies the minimal necessary changes, it performs the direct DOM manipulations, which then trigger reflow -> repaint -> recompositing of the CRP.
Notes on the stack reconciler
The order of events are:
- Function component body pushed to call stack & executed -> produces Virtual DOM nodes for itself & children. (immediate)
- Perform âdiffingâ on the virtual DOM nodes and old virtual DOM nodes.
- Recursively call the children components & push onto call stack.
As React traverses the component tree, it generates the v. DOM nodes for itself & immediate children, and diffs them in the same operation, before moving deeper.
Notes (Diffing)
- During diffing the âtypeâ and âkeyâ are used to determine if an element needs to be recreated or updated/reused.
- Same type & key -> reuse previous fiber, & update props & state
- Different type or different key -> New Fiber is created and old Fiber is marked for deletion.
The diffing algorithm is about figuring out if a component can be reused in the Fiber tree.
Summary of Stack Reconciler
In essence, the main optimisation React provides here, is identifying for the user, the minimal DOM manipulations required, which in turn, might reduce the scope of reflow / repaint / recompositing.
For example, a manual inefficient approach to a list update may involve re-clearing the entire <ul> content and re-adding each 10k items again. This would result in maximal reflow.
What weâve covered:
- Critical Rendering Path. -> How browsers convert HTML, CSS, JS to pixels on a screen, and why direct DOM manipulation can be slow.
- What is the Virtual DOM, and what are ârealâ DOM nodes in comparison.
- How the Stack reconcilliation algo. works, how it compares to manual DOM manipulation in plain JS, and its limitations.
Next: How does React Fibre overcome the limitations of the âStack reconcillerâ.
Concept: Fibre
Fibre introduces a new way to represent a âunit of workâ, alternative to the call stack based reconciller which is synchronous and non-interruptable.
Just like the virtual DOM, a âFibreâ is a lightweight JS object with more info. Each Fibre represents a unit of work. For example, a simplified fibre object:
divFibre = {
tag: 'HostComponent'
type: 'div',
key
return // parent fibre
children // points to child.
sibling // points to sibling,
... state and props
flags: 'Update' // indicate type of update needed
alternate // points to old fibre for diff
... scheduling
lanes: // priority for update
}
In summary, it holds info about the type of side effect/update to perform, the priority level for scheduling, pointer to the old fibre for diffing, and pointers to parent / children like a linked list.
What does Fibre enable?
- Time slicing / Incremental rendering. React can perform work on a subset of Fibres, pause to yield control back to the browser, then resume where it left off.
- Prioritizing of work. Different types of updates can be assigned different priorities, so more critical parts of the UI are completed first.
- Concurrency. React can start a task, pause, work on another task, and âmultitaskâ. This enables suspense for data fetching & batching of updates.
How does Fibre work?
1. Render Phase
When a component is marked and processed for rerender, React traverses the existing Fiber tree, from the root node. For each Fiber, React will:
- Check for updates
- produces the React Element for the specific component.
- Reconciles / Diffs the element with the old fibre (âalternateâ field)
- Based on 3, create or update the child fibre nodes, building the âwork-in progressâ tree. If any changes identified, the fibers are âflaggedâ and added to the list of effectful Fibers.
To summarise, in the ârenderâ phase, React will:
- Start at root node of Fiber tree, called âworkInProgressâ node.
- Execute the function, output the React Element / Virtual DOM, and Diff against the old fiber children
- Update or Create new child fibers for the workInProgress tree.
- If any DOM updates needed, fibers are flagged and added to the effectful list.
2. Commit Phase
- Using the effectful list, React iterates through and applies the DOM manipulation. This triggers the CRP steps to update the render tree, reflow, repaint, recomposite.
Afterwards when DOM is updated, lifecycle methods are executed. (useEffect)