探讨useEffect和useLayoutEffect的区别

1.背景

面试官问到:请说明下useEffectuseLayoutEffect的区别。

我:一般开发场景都是用的useEffect,react官方文档上说,两者的使用场景稍微有些不同,但是还是推荐尽量使用useEffect

面试官:不够细节,再说点,摩多摩多。

我:...

2.官网介绍

对比 useEffect useLayoutEffect
简介 useEffect 是一个 React Hook,它允许你 将组件与外部系统同步 useLayoutEffectuseEffect 的一个版本,在浏览器重新绘制屏幕之前触发。
aip useEffect(setup, dependencies?) useLayoutEffect(setup, dependencies?)
返回值 undefined undefined

3. 对比总结

3.1 useEffect

3.1.1 依赖项对effect执行的影响

  • 无依赖项:没有依赖项数组:每次重新渲染后重新运行!

  • 错误依赖项:

    • 依赖项每次渲染都不同:指定了依赖项数组,你的 Effect 仍循环地重新运行

      • => 解决:手动打印依赖项数组进行排查:console.log([dep1, dep2]);

3.1.2 运行闪烁

我的 Effect 做了一些视觉相关的事情,在它运行之前我看到了一个闪烁

  • 产生原因:useEffect是异步宏任务,在下一轮事件循环才会执行。而GUI渲染和JS线程是互斥的,也就是说,在Effect 运行前,浏览器就已经进行了屏幕渲染,渲染完毕后,useEffect才会被任务队列取出来,开始执行。

  • 解决方法:

    • 1.在得到正确的数据之前,使用loading
    • 2.使用useLayoutEffect

3.2 useLayoutEffect

3.2.1 依赖项对effect执行的影响

useEffect

3.2.2 运行闪烁

useLayoutEffect是同步任务,也就是说,他会在GUI渲染之前触发。

useLayoutEffect 内部的代码和所有计划的状态更新阻塞了浏览器重新绘制屏幕。如果过度使用,这会使你的应用程序变慢。如果可能的话,尽量选择 useEffect

  • 使用场景:

    • 在浏览器重绘前计算布局(官网以toolTip组件为例)
scss 复制代码
function Tooltip() {
  const ref = useRef(null);
  const [tooltipHeight, setTooltipHeight] = useState(0); // 你还不知道真正的高度
​
  useLayoutEffect(() => {
    const { height } = ref.current.getBoundingClientRect();
    setTooltipHeight(height); // 现在重新渲染,你知道了真实的高度
  }, []);
​
  // ... 在下方的渲染逻辑中使用 tooltipHeight ...
}

4. 一个小demo

准备了一个小demo,可以直观的体现出二者的区别

4.1 部分关键代码:

scss 复制代码
function App() {
  const [num1, setNum1] = useState(0);
  const [num2, setNum2] = useState(0);
  useEffect(() => {
    console.log("b");
    setNum1(num1 + 1);
  }, []);
  useLayoutEffect(() => {
    console.log("a");
    setNum2(num2 + 1);
  }, []);
  useEffect(() => {
    console.log(num1, num2);
  }, [num1, num2]);
  return (
    <div className="App">
      <header className="App-header">
        {num1} -- {num2}
      </header>
    </div>
  );
}

4.2 效果展示:

4.3 devtool打印结果:

浏览器设置如下:

  • chrome devtools性能节流 配置 cpu六倍降速

4.4 结果分析

5. 最后

nextTick一般用于等待dom操作完成之后马上执行:等待弹窗打开后进行数据回显,这一点来说,与useEffect的用途类似。非交互式的场景下,在执行逻辑不太多的情况下,可以使用useLayoutEffect,避免闪烁,也避免页面白屏时间过长。

6. 参考资料

React官方文档

相关推荐
kyriewen6 小时前
你的前端滤镜慢得像PPT?用Rust+WebAssembly,一秒处理4K图
前端·rust·webassembly
kyriewen116 小时前
你等的Babel编译,够喝三杯咖啡了——用Rust重写的SWC,只需眨个眼
开发语言·前端·javascript·后端·性能优化·rust·前端框架
IT_陈寒6 小时前
SpringBoot自动配置坑了我,原来要这样绕过去
前端·人工智能·后端
东方小月7 小时前
Claude Code 完整上手指南:MCP、Skills、第三方模型配置一次搞定
前端·人工智能·后端
XZ探长7 小时前
基于 Trae Solo 移动办公修复 Vue3 前端服务问题
前端
小程故事多_807 小时前
[大模型面试系列] 深度解析ReAct框架,大模型Agent的“思考+行动”底层逻辑
人工智能·react.js·面试·职场和发展·智能体
蝎子莱莱爱打怪7 小时前
Claude Code 省 Token 小妙招:RTK + Caveman 组合拳
前端·人工智能·后端
Momo__8 小时前
Vue 3.6 Vapor Mode:跳过虚拟 DOM,性能极致优化
前端·vue.js
少年白马醉春风丶8 小时前
从零构建 AIGC 无限画布:AIGCCanvasFlow 技术全解析
前端·后端·aigc
OpenTiny社区8 小时前
生成式 UI 藏大招!看似露营案例,实则电商集成 GenUI SDK 干货
前端·ai编程·交互设计