Как обрабатываются изменения в Virtual DOM?
Рендеринг и производительность
«Изменения в Virtual DOM» обрабатываются в два такта: построение нового дерева и сравнение (render-фаза), затем применение разницы к реальному DOM (commit-фаза).
Шаг 1: новое виртуальное дерево
Триггер (setState, контекст, стор, рендер родителя) заставляет React вызвать компоненты. Каждый возвращает React-элементы — лёгкие объекты { type, props }. Получается новое дерево-описание, старое (текущее) при этом сохраняется.
Шаг 2: сравнение (reconciliation)
Деревья обходятся параллельно с эвристиками, дающими O(n):
- Разный тип узла (
div→span,A→B) — старое поддерево удаляется (с размонтированием и cleanup), новое строится с нуля. - Тот же DOM-тип — узел переиспользуется; props сравниваются поверхностно, в патч попадают только отличия (className, отдельные стили, текст).
- Тот же компонент — экземпляр и state сохраняются, компонент вызывается с новыми props, рекурсия продолжается.
- Списки — дети сопоставляются по key: распознаются вставка, удаление, перемещение.
Итог — список эффектов: что вставить, удалить, переместить, какие атрибуты обновить.
Шаг 3: commit
Список применяется к реальному DOM синхронно и одним пакетом (один reflow), затем обновляются refs, выполняются useLayoutEffect, браузер рисует кадр, после — useEffect. Новое дерево становится текущим.
Свойства
Мутации данных без новой ссылки React не видит (сравнение по Object.is); render-фаза чистая и прерываемая (Fiber), commit — атомарный; переиспользование узлов сохраняет фокус, ввод и скролл.
Коротко для собеседования
Изменения обрабатываются так: строится новое виртуальное дерево → reconciliation сравнивает его со старым (тип узла, key, поверхностный дифф props) → накопленный список правок применяется к реальному DOM одним батчем в commit-фазе, затем эффекты. Рендер-фаза чистая и прерываемая, коммит — синхронный.