Что такое virtual DOM в React?
Что такое Virtual DOM
Virtual DOM (виртуальный DOM) — это концепция, при которой React хранит в памяти облегчённое представление реального DOM-дерева в виде JavaScript-объектов. Этот «снимок» синхронизируется с настоящим DOM с помощью библиотеки ReactDOM.
Зачем это нужно
Прямые манипуляции с реальным DOM — дорогостоящая операция: браузер при каждом изменении может запускать reflow и repaint всей страницы. Virtual DOM позволяет React сначала вычислить минимальный набор изменений в памяти, а затем применить их к реальному DOM одним батчем.
Как это работает: цикл обновления
1. Рендер
Когда компонент получает новые props или state, React вызывает функцию рендера и строит новое виртуальное дерево — просто JS-объекты вида { type, props, children }.
2. Diffing (reconciliation)
React сравнивает новое виртуальное дерево со старым по следующим правилам:
- Если изменился тип узла — старое поддерево уничтожается, создаётся новое.
- Если тип совпадает — обновляются только изменившиеся атрибуты.
- Для списков используются ключи (
key), чтобы отследить перемещения элементов.
3. Commit
Рассчитанный минимальный набор операций применяется к реальному DOM.
Пример
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
// При клике React строит новый виртуальный узел,
// сравнивает его со старым и обновляет только текст кнопки
return (
<button onClick={() => setCount(count + 1)}>
Счётчик: {count}
</button>
);
}
При каждом клике меняется только текстовый узел внутри кнопки — React не трогает остальной DOM.
Virtual DOM vs реальный DOM
| Virtual DOM | Реальный DOM | |
|---|---|---|
| Где живёт | Память (JS-куча) | Браузер |
| Скорость изменений | Быстро | Медленнее |
| Стоимость | Нет reflow/repaint | Есть reflow/repaint |
| Кто управляет | React | Браузер |
Важные уточнения
Virtual DOM — не «быстрее DOM» сам по себе. Преимущество в том, что React батчует изменения и минимизирует количество обращений к реальному DOM. В React 18 механизм стал ещё умнее благодаря concurrent rendering, который позволяет прерывать и приоритизировать обновления.
Что хочет услышать интервьюер
Кандидат понимает, что Virtual DOM — это JS-объект, а не магия браузера
Знает про алгоритм reconciliation и diffing
Понимает, зачем нужны ключи (key) в списках
Может объяснить, почему прямые DOM-манипуляции медленнее
Знает, что React батчует обновления перед записью в реальный DOM
Пример: Что React создаёт «под капотом» при JSX
// JSX-синтаксис
const element = <h1 className="title">Привет</h1>;
// Компилируется в вызов React.createElement,
// который возвращает простой JS-объект (виртуальный узел)
const element = React.createElement(
'h1',
{ className: 'title' },
'Привет'
);
// Результат — просто объект в памяти:
// {
// type: 'h1',
// props: { className: 'title', children: 'Привет' },
// key: null,
// ref: null
// }
Пример: Почему важны ключи при reconciliation
// Без ключей React не знает, какой элемент переместился —
// он перерендерит весь список
const BadList = ({ items }: { items: string[] }) => (
<ul>
{items.map((item) => (
<li>{item}</li> // предупреждение: отсутствует key
))}
</ul>
);
// С ключами React отслеживает каждый элемент по id —
// при сортировке DOM-узлы просто перемещаются, не пересоздаются
const GoodList = ({ items }: { id: string; label: string }[]) => (
<ul>
{items.map((item) => (
<li key={item.id}>{item.label}</li>
))}
</ul>
);
Типичные ошибки
«Virtual DOM быстрее реального DOM» — неточно: он минимизирует операции, а не заменяет браузерный движок
Путаница между Virtual DOM и Shadow DOM (это разные вещи)
Незнание роли ключей при reconciliation списков
Думают, что Virtual DOM обновляется синхронно при каждом setState отдельно, не зная про батчинг
Не могут объяснить, что именно React делает после diffing (commit-фаза)


