AcademyReact
JSX and the Virtual DOM
JSX is sugar for function calls that build plain objects, not templating — and that object tree is the whole reason React can be fast.
3 min readUpdated 3 exercises
JSX is not a templating language
JSX looks like HTML embedded in JavaScript, and that resemblance is exactly what trips people up. It is not a string, not a template, and the browser never sees it — a build step (Babel, the TypeScript compiler, or the SWC transform Next.js uses) turns it into ordinary function calls before any of this reaches a runtime.
const heading = <h1 className="title">Hello, {name}</h1>;desugars to:
const heading = React.createElement(
'h1',
{ className: 'title' },
'Hello, ',
name,
);Three arguments: what to render, its props, and its children. createElement does not touch the DOM. It returns a plain, serialisable object:
{
type: 'h1',
props: {
className: 'title',
children: ['Hello, ', name],
},
}That object is a React element. It describes a node the way a blueprint describes a house — nothing has been built yet.
Why React wants a description before it acts
Mutating the real DOM is comparatively expensive: every attribute write can trigger layout recalculation, and a browser element carries far more state than the handful of props you set. If a component re-rendered by touching the DOM directly on every state change, updating a list of 1,000 rows because one of them changed would mean 1,000 rows worth of DOM writes, whether or not the other 999 actually changed.
Elements let React sidestep that. Because a render produces a tree of plain objects — cheap to create, cheap to throw away, cheap to compare — React can build the new tree, diff it against the previous one entirely in memory, and only then touch the real DOM, and only where the two trees actually differ. The object tree is usually called the virtual DOM; the diffing pass over it is reconciliation.
// Before: type 'p', children 'Count: 0'
// After: type 'p', children 'Count: 1'
// React writes ONE text node update, nothing else on the page movesThe object representation is the mechanism, not a feature in its own right. Nobody imports "the virtual DOM" — you import React, write JSX, and the object tree is what happens on the way to the screen.
Components return elements, not markup
A function component's job is to return one element (or null), built from whatever data it was given:
function Greeting({ name }) {
return <p>Hello, {name}</p>;
}
// Called like any other function that happens to be invoked via JSX:
<Greeting name="Ada" />
// → React.createElement(Greeting, { name: 'Ada' })
// → an element whose type is the FUNCTION Greeting, not a stringThis is the detail that makes composition work: an element's type can be a string ('div', 'p', 'h1' — a DOM tag) or a function (your own component). React walks the tree, and every time it meets a function-typed element it calls that function to get the elements that function returns, recursively, until only DOM tags are left. Only then does it know what to actually paint.
The {} escape hatch
Inside JSX, {} drops you back into plain JavaScript — any expression, not a special templating syntax:
<ul>
{items.map((item) => <li key={item.id}>{item.label}</li>)}
</ul>items.map(...) is regular Array.prototype.map, returning an array of elements. JSX children accept arrays, so this is not special-cased list syntax — it falls straight out of "children are just arguments to createElement," the same as any other value would.
// The children argument to createElement can be:
// a string, a number, another element, an array of elements, or null/false
// (null and false render nothing — the common way to hide something conditionally)The one thing worth remembering
JSX compiles to function calls. Function calls return plain objects. Those objects are cheap to build and diff, and that cheapness is the entire justification for the extra layer — React never asks "did I already build this exact DOM node," it asks "does this object differ from the last one," which is a much simpler question to answer fast.
Now practice it
1 challenge · 2 quizzesReading this page is the cheap half. These are the exercises that make you use it.
- Fundamentals · React BasicsJSX desugaring, props and children basics — the questions that assume you know what createElement actually returns.QuizTake · EasyQuizTake · Easy
- Fundamentals · Component PatternsComponent-pattern questions built on the same element-tree model this page walks through from createElement up.QuizTake · MediumQuizTake · Medium
- List Reconciliation by KeyProPicks up exactly where this page stops: once JSX is a tree of objects, this is how two trees get matched up by key.ChallengeSolve · MediumChallengeSolve · Medium
Read next
Reconciliation and Why Keys Matter
The heuristic React uses to decide what to reuse and what to rebuild, and why the wrong key silently attaches state to the wrong row.
4 min
Controlled vs Uncontrolled Components
Whether React state or the DOM itself owns an input value — and the one mistake that flips a field between the two mid-render.
3 min