> Что происходит после создания work tree и current tree в React (React)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Aston
Стек: React
> Пример ответа
Короткий ответ
После создания work tree и current tree React запускает процесс reconciliation: сравнивает два дерева с помощью алгоритма diffing, вычисляет минимальный набор изменений (effect list) и применяет их к реальному DOM. Затем React синхронно выполняет commit phase: применяет side effects (useEffect, useLayoutEffect, refs) и обновляет ссылки на DOM-узлы. Этот процесс завершает цикл рендеринга и переводит приложение в новое стабильное состояние.
Подробное объяснение
После того как React построил work tree (fiber tree, представляющий новое состояние) и current tree (текущее fiber tree, соответствующее предыдущему рендеру), начинается фаза commit. Она состоит из трёх этапов:
-
Before mutation phase - React выполняет cleanup-функции из предыдущих useLayoutEffect и вызывает
getSnapshotBeforeUpdateв class-компонентах. Это синхронный проход по fiber tree. -
Mutation phase - React применяет мутации к реальному DOM: вставляет, обновляет или удаляет узлы. Здесь же сбрасываются refs (устанавливаются в null перед обновлением). Этот этап синхронный и не прерывается.
-
Layout phase - React вызывает useLayoutEffect и
componentDidMount/componentDidUpdate. После этого React планирует асинхронный вызов useEffect через scheduler (с приоритетом normal).
Важно: React не применяет изменения к DOM напрямую из work tree. Вместо этого он использует effect list - связанный список fiber-узлов, помеченных флагами (Placement, Update, Deletion). Это оптимизация, позволяющая избежать полного обхода дерева.
После завершения commit phase React переключает указатель: current tree становится равным work tree (через root.current = finishedWork). Это делает новое дерево текущим для следующего рендера.
На практике
На уровне senior важно понимать, что:
- React не гарантирует синхронность useEffect - они могут быть отложены браузером.
- useLayoutLayout выполняется синхронно до того, как пользователь увидит изменения, поэтому блокирующие операции здесь приведут к задержке отрисовки.
- При server-side rendering (SSR) useLayoutEffect выдаёт warning, так как на сервере нет DOM.
- React 18 с concurrent mode может прерывать работу над work tree, но commit phase всегда синхронна и непрерывна.
Для отладки производительности используйте Profiler API или React DevTools Profiler - они покажут, сколько времени заняла commit phase.
Пример кода
JSX// Демонстрация порядка выполненияfunction Example() {useEffect(() => {console.log('useEffect - асинхронно, после commit');});useLayoutEffect(() => {console.log('useLayoutEffect - синхронно, перед отрисовкой');});return <div>Пример</div>;}// В консоли будет:// useLayoutEffect - синхронно, перед отрисовкой// (браузер отрисовывает)// useEffect - асинхронно, после commit
Как отвечать на собеседовании
Начните с краткого определения reconciliation и commit phase. Затем опишите три этапа commit phase с акцентом на синхронность mutation и layout phase. Упомяните effect list как механизм оптимизации. Для senior-уровня добавьте про concurrent mode и отличие useEffect от useLayoutEffect. Не углубляйтесь в реализацию fiber tree, если не спросят - достаточно понимания логики.
Что проверяет интервьюер
- Понимание жизненного цикла React-компонента за пределами простого "рендер - commit".
- Знание разницы между фазами render и commit, особенно в контексте синхронности.
- Умение объяснить, почему useEffect выполняется после отрисовки браузером.
- Осведомлённость о внутренних механизмах (effect list, fiber flags) - для senior это ожидаемо.
Типичные ошибки
- Путать порядок: useLayoutLayout выполняется до, а не после useEffect.
- Думать, что React применяет изменения к DOM сразу после построения work tree - на самом деле это происходит только в mutation phase.
- Не учитывать, что commit phase не прерывается даже в concurrent mode.
- Считать, что useEffect выполняется синхронно - это асинхронный callback, запланированный через scheduler.
> Похожие задачи по frontend
Можно ли использовать key вне рендеринга списков в React
Какой роутер используется в React: нативный или сторонний
Как добавить обработчик события на DOM-элемент в React?
Является ли изменение пропсов триггером ререндеринга в React
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью