Весной стартует сезон найма, успей отхватить свой оффер!

React Fiber и процесс обновления Virtual DOM

Что такое React Fiber?

React Fiber — это новый механизм согласования (reconciliation) в React 16, который переосмысливает процесс рендеринга и обновления. Его основная цель — сделать рендеринг виртуального DOM инкрементным: разбивать его на небольшие «задачи», управлять приоритетами и повышать отзывчивость интерфейса даже при больших объёмах работы.

Основные преимущества Fiber

  1. Приоритеты обновлений
    • Задачи с более высоким приоритетом (анимации, пользовательские действия) не блокируются, а могут выполняться раньше.
  2. Разбиение рендера
    • Прервать и возобновить рендер, чтобы избежать «заморозки» интерфейса.
  3. Concurrent Mode
    • Fiber служит основой для Concurrent Mode, позволяя React работать асинхронно и адаптироваться под текущую загрузку.

Процесс обновления Virtual DOM

React использует Virtual DOM, чтобы эффективно вносить изменения в реальный DOM. Это реализуется с помощью Fiber, которая описывает структуру компонентов и отслеживает их изменения.

Render Phase (Reconciliation)

  1. Инициирование обновления

    • Каждое изменение состояния (через setState, useState) попадает в очередь обновлений (Update Queue).
    • React может объединять (batch) несколько вызовов setState в одном событии.
  2. Создание дерева Work In Progress

    • React обходит дерево Fiber, создавая «черновую» версию Virtual DOM (Work In Progress tree).
    • На этом этапе вызываются рендер-функции (или методы render для классовых компонентов), в результате чего React получает новое представление UI.
  3. Diffing

    • React сравнивает (diff) новую версию Virtual DOM (Work In Progress) со старой.
    • Если тип элементов (компонентов) совпадает, обновляются только изменённые атрибуты и дочерние узлы. Если тип меняется, React перестраивает ветку заново.
  4. Работа с ключами (key)

    • Для списков, перестановок и динамических элементов ключи (key) помогают сопоставить исходные и новые узлы, избегая полного перестроения.
  5. Сбор побочных эффектов

    • На этой фазе React определяет, какие узлы в DOM нужно добавить, удалить или изменить.
    • Формируется «список эффектов» (Effect List) — что именно должно произойти на следующем шаге.
  6. Учет приоритетов (Fiber)

    • Каждое обновление в Fiber имеет приоритет. Если возникает новая задача с более высоким приоритетом (нажатие на кнопку, скролл), React может прервать текущий рендер и вернуться к нему позже.

Важно: В Render Phase реальные изменения в DOM ещё не вносятся.


Commit Phase (Reconciliation применения)

  1. Применение изменений к реальному DOM
    • React берёт «список эффектов» (Effect List) и точечно обновляет реальный DOM: меняет атрибуты, добавляет или удаляет узлы.
  2. Вызовы жизненного цикла и хуков
    • В классовых компонентах это componentDidMount, componentDidUpdate, componentWillUnmount.
    • В функциональных компонентах — useEffect, useLayoutEffect.
  3. Batch updates (пакетные обновления)
    • Все изменения внутри одного цикла событий объединяются в один пакет, чтобы не вызывать множество мелких перерисовок.

Concurrent Mode и Fiber

Fiber — основа Concurrent Mode, который предоставляет более гибкие механизмы управления рендером. В этом режиме React может частично показывать обновлённый интерфейс, не блокируя остальную часть приложения.

Преимущества Concurrent Mode

  • Плавные анимации и переходы.
  • Асинхронная обработка сложных вычислений без «подвисаний» интерфейса.
  • Приоритетный рендер важных задач.

Ключевые идеи

  1. Virtual DOM
    • Хранит и обновляет «черновую» структуру UI в памяти, без тяжёлых операций с реальным DOM.
  2. Diffing
    • Находит отличия между старой и новой версиями Virtual DOM.
  3. Reconciliation
    • Применение изменений к реальному DOM.
  4. Fiber
    • Управляет приоритетами, прерывает и возобновляет рендер, разбивая его на небольшие части.

Учитывайте perf-особенности:

Если родительский компонент рендерится, по умолчанию его дочерние компоненты тоже повторно рендерятся. Используйте React.memo (или PureComponent в классовых компонентах), если хотите оптимизировать это поведение.