How Virtual-DOM and diffing works in React
Traversing the Component lifecycle.
Great! So now the component is marked dirty. What next? Well now the next step is to update the virtual -DOM and then use the diffing algorithm to do the reconciliation and update the actual DOM .
Before we move to the next set of steps, it is very important to be familiar with thedifferent lifecycle of a component.
And this is how our Calculator component looks in React.
Next step is to update the component.
- This is done by React running batch update.
- In the batch update, it will check if there are components marked as dirty and starts updating.
//ReactUpdates.js
var flushBatchedUpdates = function () {
while (dirtyComponents.length || asapEnqueued) {
if (dirtyComponents.length) {
var transaction = ReactUpdatesFlushTransaction.getPooled();
transaction.perform(runBatchedUpdates, null, transaction);
3. Next, it will check if there is any pending state that has to be updated or a if a forceUpdate is issued.
if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
In our case, you can see in the calculator wrapper, this._pendingStateQueue
4. First it will check if we have used and if we have used it, allows us to update the state with the new props that we received.
5. Next it will check if we have used and if we have used, we can check if a component should be re-render with the change in state or props.
Use this when you know of scenarios where you don’t need the component to re-render, and therefore improving on the performance.
From Steps 4,5 and 6, we only use render()
7. Now let us look more into what happens during render().
Render is where the Virtual DOM gets re-build and the diffing happens
Rendering the Component — Updating the Virtual-DOM, running the diffing algorithm and updating the actual DOM
In our example, all the elements under the component is build again in the Virtual DOM.
It will check if the previous and next rendered element are of same type and key, and then reconcile the component the type and key matches.
var prevRenderedElement = this._renderedComponent._currentElement;
var nextRenderedElement = this._instance.render(); //Calculator.render() method is called and the element is build.
Important point to note is, here is where our component’s render method is called. i.e Calculator.render()
The reconciliation process in general goes through the below steps.
The red dotted lines means, all the reconciliation step will be repeated for the next child or children within this child
The above flowchart that I have prepared summarizes about how the Virtual DOM is used to update the actual DOM.
I may have missed a few steps knowingly or unknowingly, but this diagram covers most of the key steps.
Therefore you can see how in our example, the reconciliation would be done as below:
I will walk you through of updating the DOM to Output:150 and skipping the reconciliation steps of previous <div>
's
- Reconciliation starts from the main
<div>
of the component which is the one with class=”container”. - Its child is
<div>
which contains Output, and therefore react will start reconciliation of this child. - Now this child has it’s own children
<hr>
and<h2>
- So react will start reconciliation for
<hr>
- Next, it will start with reconciliation of
<h2>
and since it has it’s own children which are the texts Output: and the output from state, it will start reconciliation for these two. - First Output: text goes through reconciliation and since there is no change, nothing happens to the DOM.
- Next, output from state goes through reconciliation and since we have a new value now, i.e 150, react will update the actual DOM.