How is React able to update only the parts of the DOM that require updating (because they’ve changed) as opposed to re-rendering the entire DOM?
From what I understand, regular HTML/Javascript web pages react to changes in the DOM by re-rendering the entire DOM. I also understand that React uses a virtual DOM to determine what has changed and what has not. It compares the previous state of the virtual DOM with the new one to determine what has changed and updates the real DOM to match the virtual DOM only on the nodes that have changed. I also understand that when transpiled, React code is converted to regular Javascript.
Putting this all together leads to the question above. If React just becomes regular Javascript after transpilation, then at run time, it’s the same situation as a regular HTML/Javascript web page. But this is said to render the entire DOM in response to any change in the DOM. So how does the code only update the parts of the DOM that need updating? The browser doesn’t know (nor would it care) that it used to be React code, so why should it handle the DOM any differently than a regular HTML/Javascript web page? Is there a way in plain Javascript to tell it to update only part of the DOM instead of re-rendering the entire DOM? Is that what a React application is doing after being transpiled to plain Javascript?
2
Answers
When you do something like this:
It gets transpiled to something like this:
That
jsx
function returns a small object which looks roughly like this:In more complicated examples the
children
property can be (and often is) another element, which could then have children of its own, and so on. So as your components render you are building up a bunch of these objects in a tree.To figure out what has changed, react compares the tree from the previous render with the new tree. For a given element, react first looks at the type and key. If either one of those has changed, then this is a new element; it must be unmounted and a new one mounted in its place. If the type and key match, it next checks the props. If the props have changed, then it knows it needs to update that prop.
After that it repeats the comparison for the children of the element, then the children’s children, etc. At the end it has built up a list of changes, and it then pushes those changes (if any) to the DOM, using built in browser functions like document.append.
DOM Manipulation, as you know, is an expensive process. The reflow, the repaint, executing the scripts, all of that takes a toll on the browser. React is efficient exactly for the optimized the diffing and the reconciliation algorithms.
React maintains a lightweight virtual DOM, which is nothing but just a JavaScript object. It compares the differences between the new VDOM and the current one every time it’s required to re-render the component.
Think of it this way. What makes React re-render its components? Any changes in state variable or props values. So, React does not need to update the whole DOM tree. It updates only what is necessary. In other words, only the elements that are dependent on the props data or the state variable.
Now, it’s not like after transpilation React turns into regular JavaScript; but rather, React itself is just a bunch of functions and algorithms written in JavaScript. It’s the JSX codes that get transpiled into a React element (which is again just a JS object). So, when you write React code like setState or useState, React internally manages the state and invokes its algorithms to compute changes and re-render the component, allowing partial updates to the real DOM.
At runtime, the browser still executes this JavaScript logic, which includes React’s diffing algorithm to figure out which DOM elements need to change. So, it’s not that the browser suddenly “knows” the code came from React; instead, it’s React’s efficient DOM manipulation logic embedded in the JavaScript code that ensures partial updates.
Makes sense? Upvote pls 🙂