浅谈useLayoutEffect 与 useEffect 的联系与区别

91 阅读2分钟

useLayoutEffect 与 useEffect 是 React 中处理副作用的两个核心 Hook,它们的联系和区别如下:


一、​​联系​

  1. ​功能定位​
    两者均用于处理组件中的副作用操作(如数据获取、DOM 操作、订阅事件等),且函数签名一致(接收回调函数和依赖项数组)。
  2. ​清理机制​
    均支持通过返回清理函数实现副作用的清理逻辑(如取消订阅、清除定时器)。
  3. ​依赖项管理​
    依赖项数组的机制相同,依赖项变化时触发副作用重新执行。

二、​​区别​

​特性​​useEffect​​useLayoutEffect​
​执行时机​浏览器渲染完成后异步执行DOM 更新后、浏览器绘制前同步执行
​阻塞渲染​不阻塞,用户可立即看到渲染结果阻塞,需等待副作用执行完毕才渲染
​适用场景​数据获取、事件订阅、非视觉操作同步更新 DOM、测量布局、避免页面闪烁
​性能影响​无阻塞,性能更优同步操作可能阻塞渲染,导致卡顿
​服务端渲染​支持不支持(无 DOM,无实际效果)

三、​​核心差异解析​

  1. ​执行时机​

    • ​useEffect​​:在浏览器完成页面渲染后异步执行,属于宏任务(MacroTask),不会阻塞用户交互。
    • ​useLayoutEffect​​:在 DOM 更新后、浏览器绘制前同步执行,属于同步任务,会阻塞渲染流程。
  2. ​使用场景​

    • ​useEffect​​:适合大多数场景,如网络请求、事件监听等异步操作。
    • ​useLayoutEffect​​:需直接操作 DOM 或同步更新布局时使用(如测量元素尺寸、调整样式避免闪烁)。
  3. ​性能优化​

    • ​useEffect​​:异步执行避免阻塞,优先推荐使用。
    • ​useLayoutEffect​​:需避免耗时操作,否则会导致页面卡顿。

四、​​代码示例对比​

// 使用 useEffect(异步执行,可能闪烁)
useEffect(() => {
  console.log("useEffect - 异步更新");
  document.title = "异步更新标题";
}, []);

// 使用 useLayoutEffect(同步执行,无闪烁)
useLayoutEffect(() => {
  console.log("useLayoutEffect - 同步更新");
  document.title = "同步更新标题";
}, []);
  • ​现象​​:useLayoutEffect 的修改会立即生效,而 useEffect 的修改可能在下一次渲染后生效。

五、​​总结​

  • ​优先使用 useEffect​​:异步特性避免阻塞渲染,适合 90% 的场景。
  • ​谨慎使用 useLayoutEffect​​:仅在需要同步操作 DOM 或避免视觉不一致时使用,并确保操作轻量。