В React порядок вызова и срабатывания хуков и логов следующий:
const Effects = () => {
В React порядок вызова и срабатывания хуков и логов следующий:
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
const Effects = () => { const [count, setCount] = useState(0);
useLayoutEffect(() => console.log("each render 1"));
console.log("each render 2");
useEffect(() => console.log("each render 3"));
return ( <> {count} <button onClick={() => setCount((prevProps) => ++prevProps)}> Increment </> ); };
export default Effects;
// 1 рендер: // После клика:
const Effects = () => { const [count, setCount] = useState(0); const [number, setNumber] = useState(0);
useEffect(() => { console.log(count);
return () => {
console.log(count);
};
});
return ( <> {count} <button onClick={() => setCount((prevProps) => ++prevProps)}> Increment </> ); };
export default Effects;
// 1 рендер: // 2 1 3 // После клика: // 2 1 3 // return null: // 2 1 3 // // 1: 1, 0 // +: 1, 2 // ++: 2, 2
Ответ
В React порядок вызова и срабатывания хуков и логов следующий:
- При каждом рендере сначала выполняется тело компонента, где вызывается
console.log("each render 2"). - Затем вызывается
useLayoutEffect, который срабатывает синхронно сразу после изменения DOM, но до того, как браузер отрисует изменения. Там вызываетсяconsole.log("each render 1"). - После того, как браузер отрисовал изменения, вызывается
useEffect, где вызываетсяconsole.log("each render 3").
Таким образом, при монтировании и обновлении порядок логов будет:
each render 2
each render 1
each render 3
При размонтировании useEffect и useLayoutEffect могут возвращать функции очистки, но в данном примере их нет, поэтому логов при размонтировании нет.
Пример с пояснениями:
import React, { useState, useEffect, useLayoutEffect } from 'react';
export default () => {
const [count, setCount] = useState(0);
useLayoutEffect(() => {
console.log("each render 1");
});
console.log("each render 2");
useEffect(() => {
console.log("each render 3");
});
return (
<button onClick={() => setCount(prev => prev + 1)}>
Increment
</button>
);
}
Важно: useLayoutEffect блокирует отрисовку до выполнения, а useEffect выполняется асинхронно после отрисовки.