JSX and the Virtual DOM: A Peek Under the Hood
I recently completed a mock technical interview with Skilled Inc. to test my React knowledge. Though I scored a 4/5 and earned generally favorable remarks, my interviewer suggested a deeper dive into how JSX and the Virtual DOM actually work. Not just what they are, but how they are. I understood the higher-level concepts and answered all of his basic inquiries, but he caught me on this “gotcha” question: “Where does the Virtual DOM live?”
Don’t know the answer, either? Don’t fret—just keep on reading. This blog’s for you!
JSX
This React-specific syntax is an extension of JavaScript that allows for writing HTML and JavaScript together. It is not necessary to write React code with JSX, but it simplifies the UI design process, allows for a cleaner file structure, and helps generate useful React error messages. It looks like this.
const bestSportsTeam = <p>Carolina Panthers, duh.<p>return (
<div>
{bestSportsTeam}
</div>
)
The result is the following, rendered to the (actual) DOM.
<div>
<p>
Carolina Panthers, duh.
</p>
</div>
So, how does this work? When React runs JSX through the compiler, it turns the code into traditional JavaScript objects. It accomplishes this through a series of React.createElement() calls. The bestSportsTeam variable referenced above becomes:
const bestSportsTeam = React.createElement(
'p',
'Carolina Panthers, duh.'
)
We’re almost there. One last step. What does React.createElement actually do? It spits out a plain, cheaply created JavaScript object, which ReactDOM then mounts to the DOM.
The Virtual DOM
All right, we’ve connected how JSX creates React elements that in turn become JavaScript objects. How, though, are React elements used to construct the DOM, and where does the concept of the Virtual DOM come into play?
The DOM, which stands for Document Object Model, is a tree data structure that controls what’s rendered on a user’s screen. It’s the UI representation of an app in a browser. Each element is a node in the tree.
DOM manipulation lies at the heart of modern web development, but at times it can be redundant. Let’s say you have an unordered list of the Carolina Panthers roster. As players are cut and added during the offseason, the roster changes. Most JavaScript processes to handle these updates would require rebuilding the entire list. The Virtual DOM, however, is smart enough to recognize only the list items that have changed and leave the rest alone, re-rendering only what’s necessary.
How? The Virtual DOM—which lives in memory, by the way, to answer the question in the intro—serves as a lightweight copy of the real DOM. It’s a representational version that lacks the power to actually manipulate what’s on the screen. When you change an application’s state, React produces two depictions of the Virtual DOM: one that represents the DOM tree pre-update, and one which represents the DOM tree post-update. React then runs an algorithm that compares the two versions and logs the changes, a process called diffing.
Finally, in one last task known as reconciliation, the ReactDOM library syncs the new version of the Virtual DOM with the actual DOM, updating what’s displayed on the screen. In our example of the Carolina Panthers roster, only the effected list items would get re-rendered, and not the entire list.
To recap:
JSX
- An extension of JavaScript that allows writing HTML and JavaScript together in one file.
- Accomplished through a series of React.createElement() calls.
- When compiled, JSX is turned into cheap, plain JavaScript objects to be rendered to the DOM.
Virtual DOM
- An application’s state changes.
- React creates a new version of the Virtual DOM and compares the pre-update Virtual DOM with the post-update Virtual DOM (diffing).
- Only the elements that were changed are updated on the actual DOM through the ReactDOM library (reconciliation).
- The browser updates and the new application state is displayed on the screen.