Когда происходит контроль изменений в VDOM?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда происходит контроль изменений в VDOM?
VDOM (Virtual DOM) — это абстрактное представление реального DOM в памяти. React использует VDOM для оптимизации обновлений UI. Давайте разберёмся, когда именно происходит контроль изменений.
Жизненный цикл VDOM обновлений
1. Trigger (Триггер) 2. Render phase (синхронный, может быть прерван) 3. Reconciliation (сравнение VDOM) 4. Commit phase (применение изменений в DOM) 5. Layout & Paint 6. Browser repaint
1. Trigger — что вызывает контроль изменений?
- setState вызывает контроль изменений
- props изменились
- Прямое изменение DOM (но это плохо)
- Обычное переприсваивание НЕ работает в React
2. Render Phase (Синхронный)
В этой фазе React:
- Вызывает функцию компонента (функциональный компонент)
- Вызывает render() метод (классовый компонент)
- Создаёт новый VDOM tree
Важно: Render phase может быть прерван (Concurrent features в React 18+).
3. Reconciliation — контроль изменений (Diffing)
React сравнивает старый VDOM с новым:
Алгоритм:
- Если type изменился — замени весь узел
- Если props изменились — обнови props
- Рекурсивно сравни children
Контроль по ключам (keys):
- Правильно: key={item.id} (уникальный ключ)
- Неправильно: key={index} (может спутать элементы)
Без key с индексом: [A, B, C] → [B, C] → React может подумать что A → B, B → C, C удалён Это приводит к неправильному обновлению.
4. Commit Phase — применение в DOM
Здесь React:
- Удаляет узлы из DOM
- Добавляет новые узлы
- Обновляет props в реальном DOM
- Запускает lifecycle методы (useEffect, componentDidMount и т.д.)
Порядок:
- Render phase (функция вызывается)
- Reconciliation (сравнение VDOM)
- Commit phase (DOM обновляется)
- useEffect выполняется
Batch updates (React 18+)
React объединяет несколько setState в один Render плюс Commit:
function handleClick() {
setCount(c => c + 1);
setName('John');
// Оба setState объединены в один цикл
// Контроль изменений произойдёт один раз!
}
Но в асинхронном коде это не работает:
setTimeout(() => {
setCount(c => c + 1); // Один render
setName('John'); // Второй render (два раза проверка!)
}, 0);
Shallow comparison (поверхностное сравнение)
React сравнивает поверхностно:
const oldProps = { user: { name: 'John' } };
const newProps = { user: { name: 'John' } };
oldProps.user === newProps.user // false (разные объекты в памяти!)
// React подумает что props изменились
Правильно — используй useMemo:
const user = useMemo(() => ({ name: 'John' }), []);
// Теперь объект не пересоздаётся каждый раз
Оптимизация контроля изменений
1. React.memo — пропустить render если props не изменились
const MyComponent = React.memo(({ name }) => <div>{name}</div>);
2. useMemo — кэшировать вычисления
const memoizedValue = useMemo(() => expensiveCalculation(), [deps]);
3. useCallback — кэшировать функцию
const memoizedCallback = useCallback(() => { ... }, [deps]);
4. Правильные keys в списках
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
Контроль изменений в классовых компонентах
class Counter extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// Контроль: обновлять ли компонент?
if (nextState.count === this.state.count) {
return false; // Не обновлять
}
return true;
}
}
Итог
Контроль изменений в VDOM — это:
- Быстро — только нужные части DOM обновляются
- Автоматически — React управляет процессом
- Оптимизируемо — используй memo, useMemo, useCallback
- Предсказуемо — правильные keys и shallow comparison