TL;DR
React Fiber — это переработанный движок согласования (reconciliation) в React, который реализует инкрементальный рендеринг через linked list of fibers. Он позволяет прерывать и возобновлять работу, приоритезировать задачи и эффективно обновлять DOM. Разберёмся, как это работает под капотом.
Введение: эволюция рендеринга в React
До Fiber React использовал синхронный стековый алгоритм reconciliation, который не мог быть прерван. Это вызывало проблемы с производительностью в complex UIs. Fiber архитектура (появилась в React 16) решает это через:
- Разбиение работы на chunks
- Приоритизацию обновлений (например, анимации > data fetching)
- Возможность паузы/возобновления работы
// До Fiber - recursive tree traversal
function reconcile(prev, next) {
// ...рекурсивный обход всего дерева
}
Как устроен Fiber node
Каждый Fiber — это lightweight JavaScript object, представляющий единицу работы. Основные поля:
{
tag: FunctionComponent | ClassComponent | HostComponent,
key: null | string,
elementType: string | Function,
stateNode: DOMNode | Instance,
return: Fiber | null,
child: Fiber | null,
sibling: Fiber | null,
alternate: Fiber | null, // для diffing
effectTag: Placement | Update | Deletion,
nextEffect: Fiber | null // linked list изменений
}
Фактически, Fiber — это immutable work-in-progress tree, где каждый узел знает:
- Свои зависимости (child/sibling)
- Альтернативную версию (previous state)
- Эффекты, которые нужно применить
Фазы рендеринга
Fiber разделяет рендеринг на две фазы:
-
Render phase (прерываемый):
- Создание work-in-progress tree
- Вызов render методов
- Сравнение с предыдущей версией (reconciliation)
-
Commit phase (синхронный):
- Применение изменений к DOM
- Вызов lifecycle методов
- Запуск эффектов
// Упрощённый цикл работы Fiber
function workLoop(deadline) {
while (nextUnitOfWork && deadline.timeRemaining() > 0) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
if (!nextUnitOfWork && workInProgressRoot) {
commitRoot();
}
requestIdleCallback(workLoop);
}
Приоритизация задач
Fiber использует browser’s requestIdleCallback API (или полифиллы) для планирования работы:
const priorities = {
Immediate: 1, // Ввод пользователя
UserBlocking: 2, // Анимации
Normal: 3, // Обычные обновления
Low: 4, // Отложенные задачи
Idle: 5 // Не критично
};
function scheduleUpdate(fiber, priority) {
// ...логика добавления в очередь
}
Практические следствия
- Оптимизация рендеринга:
- Используйте React.memo/PureComponent для предотвращения лишних ререндеров
- Разбивайте тяжёлые компоненты на мелкие
const HeavyComponent = React.memo(({ items }) => (
<div>
{items.map(item => (
<Item key={item.id} {...item} />
))}
</div>
));
- Работа с Concurrent Mode:
- Используйте Suspense для ленивой загрузки
- Применяйте startTransition для не критичных обновлений
function App() {
const [resource] = useState(() => createResource(fetchData()));
return (
<Suspense fallback={<Spinner />}>
<Profile resource={resource} />
</Suspense>
);
}
Под капотом: diffing алгоритм
Fiber использует two-pass алгоритм сравнения:
- Первый проход (begin phase): создание work-in-progress tree
- Второй проход (complete phase): сбор эффектов
function performUnitOfWork(fiber) {
// begin phase
const children = reconcileChildren(fiber, fiber.props.children);
if (fiber.child) return fiber.child;
// complete phase
let nextFiber = fiber;
while (nextFiber) {
completeWork(nextFiber);
if (nextFiber.sibling) return nextFiber.sibling;
nextFiber = nextFiber.return;
}
}
Заключение
React Fiber — это эволюция core алгоритма React, которая:
- Делает рендеринг инкрементальным и прерываемым
- Позволяет приоритезировать задачи
- Сохраняет семантику “UI как функция состояния”
Для глубокой оптимизации приложений понимание Fiber architecture критически важно. Используйте React DevTools Profiler для анализа производительности и помните: чем меньше Fiber nodes нужно обработать — тем быстрее ваш UI.
Источник: https://inside-react.vercel.app/blog/how-does-react-fiber-render-your-ui