Updating a page by hand means mixing application logic with instructions for changing browser nodes. A virtual DOM lets you describe what the view should look like instead. It is a lightweight JavaScript tree that represents the browser’s DOM; it is not the browser’s DOM itself. A framework uses that description to create the view and, when it changes, decide which browser nodes need updating. Not every framework uses this approach. section 3.2 section 1.3.2
Each object in the tree is a virtual node. An element node records its tag, properties, and children; a text node records text; and a fragment groups nodes without adding a parent element. Child order matters. Properties can include attributes and event handlers, even though handlers added programmatically do not appear in HTML markup. section 3.2 section 3.4
{
type: 'element',
tag: 'form',
props: { action: '/login', class: 'login-form' },
children: [
{
type: 'element',
tag: 'input',
props: { type: 'text', name: 'user' }
},
{
type: 'element',
tag: 'input',
props: { type: 'password', name: 'pass' }
},
{
type: 'element',
tag: 'button',
props: { on: { click: () => login() } },
children: [
{
type: 'text',
value: 'Log in'
}
]
}
]
}
The login-form tree shows how plain objects retain the form’s attributes, ordered inputs, button text, and click handler. section 3.2
To build a small virtual DOM:
- Give each node a type: text, element, or fragment. section 3.4
- Create elements with h(tag, props, children). Use hString() for text and hFragment() for a group without a parent element. section 3.5 section 3.9
- Write component functions that receive state and return virtual nodes. Compose smaller functions to describe larger views. section 3.8.1 section 3.8.3
A list that follows state
A function can return h('ul', {}, todos.map(todo => h('li', {}, [todo]))). Pass it two to-do descriptions and it describes a list with two items. When the state gains an item, call the function again to produce a new tree. The framework renders the tree into browser nodes and updates those nodes to reflect the change. section 3.8.2 section 1.3.2
Updating does not require rebuilding the entire browser view. A reconciliation algorithm compares the old and new virtual trees to find changes such as modified attributes, changed text, or an added node, then applies the needed changes to the DOM. For server-rendered HTML, hydration instead begins by matching existing HTML elements to virtual nodes and attaching event handlers. section 7.2.1 section 1.3.3

