Порядок рендера компонентов и вызова хуков в React
В React важно понимать порядок рендера компонентов и вызова хуков, особенно при оптимизации производительности и отладке поведения компонентов.
Порядок рендеринга компонентов
Когда React начинает рендер, он следует следующему порядку:
1. Вызов родительского компонента
React вызывает функцию родительского компонента, чтобы получить его JSX.
2. Рекурсивный рендер дочерних компонентов
В JSX родителя React находит все вложенные компоненты и вызывает их один за другим.
3. Построение виртуального DOM
На основе всех JSX-выражений строится виртуальное дерево компонентов.
4. Сравнение (diffing) и обновление DOM
React сравнивает новое дерево с предыдущим и обновляет только изменившиеся части.
Порядок вызова хуков
Хуки в React вызываются в строго определённом порядке, чтобы React мог сопоставить значения хуков с их предыдущими значениями во время повторных рендеров.
Порядок
-
useState
,useReducer
,useContext
и другие синхронные хуки- Вызываются сразу при рендере компонента, в том порядке, в котором они объявлены в функции.
- React сохраняет значения хуков по их порядку в «внутреннем списке».
-
useLayoutEffect
- Выполняется после того, как DOM обновился, но до того, как браузер нарисует изменения.
- Полезно, если нужно измерить размеры DOM или синхронно взаимодействовать с layout.
-
useEffect
- Вызывается после того, как браузер отрисовал страницу.
- Используется для побочных эффектов, подписок, запросов, таймеров и т.д.
❗ Важно: не нарушайте порядок хуков
React полагается на фиксированный порядок вызова хуков между рендерами. Поэтому:
Нельзя вызывать хуки внутри:
- Условий
if
- Циклов
for
,while
- Вложенных функций
Нужно вызывать хуки всегда на верхнем уровне функции-компонента.
// Плохо
if (show) {
useEffect(() => {}, []);
}
// Хорошо
useEffect(() => {
if (show) {
// логика
}
}, [show]);
Итог
- React сначала вызывает родительские компоненты, потом рендерит дочерние.
- Хуки вызываются в том порядке, как они написаны в теле функции.
useState
иuseEffect
— это не просто функции, а механизм управления жизненным циклом.useLayoutEffect
— синхронный,useEffect
— асинхронный (по отношению к рендеру).
Важно:
Нарушение порядка вызова хуков приведёт к ошибке исполнения и некорректной работе компонента.