React’s core idea is smaller than it looks: describe your UI as plain JavaScript objects (a virtual DOM), then have a render function translate those objects into real DOM nodes. Here we build both — in about 20 lines — and watch a tree of objects become actual elements on the page.
{
"type": "div",
"props": {
"attrs": {
"id": "tiny-root"
},
"children": [
{
"type": "h1",
"props": {
"attrs": {},
"children": [
{
"type": "TEXT_ELEMENT",
"props": {
"nodeValue": "Hello Tiny React",
"children": []
}
}
]
}
},
{
"type": "p",
"props": {
"attrs": {},
"children": [
{
"type": "TEXT_ELEMENT",
"props": {
"nodeValue": "Rendered by a 20-line renderer",
"children": []
}
}
]
}
}
]
}
}<div>, <h1> and <p> nodes, created by our renderer.type and props. Right: the real DOM our render function produced from it.createElement doesn’t touch the DOM at all. It just returns a plain object describing what you want: a type ("div", "h1", …), its attributes, and its children. Strings become special text nodes. This is exactly what JSX compiles into — <h1>hi</h1> becomes createElement("h1", null, "hi").
render walks that object tree recursively. For a text node it creates a real text node; for an element it creates the tag, copies attributes across, and recurses into the children — appending each result to its parent. One depth-first pass turns the whole virtual tree into live DOM.