useEffect vs useLayoutEffect

124 阅读1分钟

在 React 中,useEffect 和 useLayoutEffect 都是用于处理副作用的 Hook,但它们的执行时机不同,这导致了在更新状态时对渲染行为的影响也有所不同。本文将通过两个例子来展示它们之间的区别。

两个例子都是在render后再次更新state重新触发render,唯一差别是一个使用useEffect,而一个使用useLayoutEffect

使用useEffect

const Component = ({containerState}) => {
    console.log('component rendered')
    const [state, setState] = useState(1);
    useEffect(() => {
        console.log('component mounted')
        return () => {
            console.log('component unmounted')
        }
    }, [])
    return <>
        <h1>{state}</h1>
        <button onClick={() => {
            setState((state) => state + 1)
        }}>state
        </button>
    </>
}

Screen Recording 2025-03-13 at 10.51.15 PM.gif

可以看到使用useEffect更新具有明显闪屏,从先绘制1,后更新重新绘制为2

使用useLayoutEffect

const Component = ({containerState}) => {
    console.log('component rendered')
    const [state, setState] = useState(1);
    useLayoutEffect(() => {
        console.log('layoutEffect mounted')
        setState((state) => state + 1)
        return () => {
            console.log('layoutEffect unmounted')
        }
    }, []);
    return <>
        <h1>{state}</h1>
        <button onClick={() => {
            setState((state) => state + 1)
        }}>state
        </button>
    </>
}

Screen Recording 2025-03-13 at 10.54.40 PM.gif

而使用useLayoutEffect更新state则直接绘制为2,因为useLayoutEffect执行在render函数执行之后,第一次绘制之前

生命周期图示

下图展示了 React 组件的生命周期,特别是 useEffectuseLayoutEffect 的执行时机:

QQ_1741878244399.png 原图来自 projects.wojtekmaj.pl

总结

  • useEffect:适合大多数副作用场景,执行时机在渲染完成后异步执行,可能会导致页面闪烁。
  • useLayoutEffect:适合需要在 DOM 更新后立即同步执行的场景,能够避免页面闪烁,但可能会阻塞渲染。