Как JSX трансформируется в DOM?
Компоненты
Путь JSX до DOM — три стадии: компиляция (сборка), создание элементов (рантайм) и рендер + коммит (React).
Стадия 1: компиляция (build time)
Браузер JSX не знает. Babel/TypeScript при сборке превращают разметку в вызовы функций:
<button className="buy" onClick={buy}>Купить</button>
// ↓
_jsx('button', { className: 'buy', onClick: buy, children: 'Купить' })Стадия 2: React-элементы (runtime)
При выполнении кода эти вызовы возвращают элементы — лёгкие объекты-описания:
{ type: 'button', props: { className: 'buy', onClick: buy, children: 'Купить' } }Это ещё не DOM — только план. Вызовы компонентов (type — функция) React разворачивает, вызывая их и получая их элементы, — так строится полное дерево (Virtual DOM).
Стадия 3: рендер и коммит (React DOM)
- Первый рендер: React обходит дерево элементов и для каждого host-узла вызывает document.createElement, выставляет атрибуты/свойства, собирает и вставляет в контейнер (
createRoot(...).render(<App />)). Обработчики не вешаются на узлы — работают через делегирование с корня. - Обновления: новое дерево элементов сравнивается со старым (reconciliation), в DOM вносятся только отличия: изменить textContent, добавить/удалить узел, обновить атрибут.
Итоговая цепочка
JSX → (Babel/TS) вызовы _jsx → React-элементы (объекты)
→ рендер компонентов → дерево → дифф → (react-dom) createElement/патчи → DOMКоротко для собеседования
JSX не «превращается в DOM» напрямую: сборка компилирует его в вызовы _jsx/createElement; в рантайме они дают React-элементы (объекты-описания); react-dom при первом рендере создаёт по ним реальные узлы, а при обновлениях диффом вносит в DOM только изменения.