Virtual DOM (VDOM aka VNode) is magical ✨ but is also complex and hard to understand😱. React, Preact and similar JS libraries use them in their core. Unfortunately I couldn’t find any good article or doc that explains it in a detailed-yet-simple-to-understand fashion. So I thought of writing one myself.

Note: This is a LONG post. I’ve added tons of pictures to make it simple but it also makes the post appear even longer. I’m using Preact’s code and VDOM as it is small and you can look at it yourself with ease in the future. But I think most of the concepts applies to React as well. My hope is that once you read this, you’ll be able to better understand and hopefully contribute to libraries like React and Preact.

In this blog, I’ll take a simple example and go over various scenarios to give you an idea as to how they actually work. Specifically, I’ll go over:

Babel and JSX Creating VNode — A single virtual DOM element Dealing with components and sub-components Initial rendering and creating a DOM element Re-rendering Removing DOM element. Replacing a DOM element.

The app:

The app a simple filterable Search app that contains two components “FilteredList” and “List”. The List renders a list of items (default: “California” and “New York”). The app has a search field that filters the list based on the characters in the field. Pretty straight forward.

Picture of the app (Click to zoom and see the details)

The Big Picture

At a high-level, we write components in JSX(html in JS), that gets converted to pure JS by CLI tool Babel. Then Preact’s “h” (hyperscript) function, converts it into VDOM tree (aka VNode). And finally Preact’s Virtual DOM algorithm, creates real DOM from the VDOM that creates our app.

The big picture

Before we get into the weeds of the VDOM lifecycle, let’s understand JSX as it provides the starting point for the library.

1. Babel And JSX

In React, Preact like libraries, there is no HTML and instead everything is JavaScript. So we need to write even the HTML in JavaScript. But writing DOM in pure JS is a nightmare!😱

For our app we’ll have to write HTML like below:

Note: I’ll explain “h” soon

That’s where JSX comes in. JSX essentially allows us to write HTML in JavaScript! And also allows us to use JS within that by curly braces{}.

JSX helps us easily write our components like below:

Converting JSX tree to JavaScript

JSX is cool but it’s not a valid JS, but ultimately we need REAL DOM. JSX only helps in writing a representation of real DOM and otherwise it’s useless.

So we a way need to convert into a corresponding JSON object (VDOM, which is also a tree) so we can eventually use it as an input to create real DOM. We need a function to do that.

And that function is the “h” function in Preact. It’s the equivalent to “React.createElement” in React.

“h” stands for hyperscript — one of the first libs to create HTML in JS (VDOM)

But how to convert JSX into “h” function calls? And that’s where Babel comes in. Babel simply goes through each JSX node and converts them to “h” function calls.

Babel JSX (React Vs Preact)

By default, Babel converts JSX to React.createElement calls because it defaults to React.

LEFT: JSX RIGHT: React version of JS (click to Zoom)

But we can easily change the name of the function to anything we want (like “h” for Preact) by adding “Babel Pragma” like below: