useEffect 与 useLayoutEffect 的区别

useEffect和useLayoutEffect是处理副作用的React钩子函数,有以下区别

1. 执行时机不同
  • useEffect:在组件渲染到屏幕之后异步执行。这意味着它不会阻塞浏览器的绘制和更新,适用于大多数与数据获取、订阅事件、手动修改DOM等不会直接影响页面布局和视觉呈现的操作。
  • useLayoutEffect:会在浏览器进行布局和绘制之前同步执行。useLayoutEffect中执行的操作会修改DOM样式或结构,并且在浏览器绘制之前就完成这些修改,避免页面的重绘和回流带来的性能问题。

    注意:useLayoutEffect是在DOM结构更新后、渲染前执行,在渲染时是同步执行,相当于有一个防抖效果

2. 对性能影响不同
  • useEffect:由于是异步执行,不会阻塞页面的渲染,对用户交互的响应性影响较小,但如果副作用操作耗时较长,可能会在用户操作后有短暂的延迟才看到效果。
  • useLayoutEffect:由于是同步执行,如果在其中执行的操作耗时较长,会阻塞页面的渲染,可能导致页面卡顿,影响用户体验。
3. 对渲染的影响不同:
  • useEffect 的执行不会阻塞浏览器的渲染工作
  • useLayoutEffect 的执行可能会阻塞浏览器的渲染,使用 useLayoutEffect 时需要注意性能问题。
4. 使用场景不同
  • 一般情况下,如果副作用操作不会影响页面的布局,建议使用useEffect。例如发送网络请求获取数据、添加事件监听器、更新本地存储等。
  • 如果副作用操作会影响页面的布局和视觉呈现,例如直接修改DOM元素的样式、位置、大小等,为了避免页面的闪烁和重绘,建议用useLayoutEffect

    useLayoutEffect会在浏览器进行布局和绘制之前同步执行。这意味着它可以在 DOM 更新后、浏览器绘制之前进行操作,从而避免由于异步的useEffect可能导致的闪烁现象。

使用建议

  1. 将直接影响页面布局和视觉呈现的操作放在useLayoutEffect中,例如直接修改 DOM 元素的样式、位置、大小等。因为它会等待这些操作完成后再进行渲染,所以可以避免页面的闪烁。
  2. 减少useLayoutEffect中执行的复杂或耗时操作。由于它是同步执行,如果操作过于耗时,可能会阻塞页面的渲染,导致卡顿。如果必须进行复杂计算或耗时操作,可以考虑将其拆分为异步操作,或者在操作完成后再进行必要的 DOM 更新。
  3. 精确管理依赖项,只将会影响布局的变量添加到依赖项数组中。这样可以避免不必要的useLayoutEffect执行。
### useEffectuseLayoutEffect的执行顺序 在React中,`useEffect` `useLayoutEffect` 的主要区别在于它们何时触发以及如何处理副作用。对于 `useEffect` 而言,在浏览器完成布局绘制之后才会调用它所定义的效果函数[^1];而对于 `useLayoutEffect` 来说,则是在所有的DOM变更发生后但在浏览器执行绘制前同步调用效果函数。 具体来说: - 当组件首次渲染或状态发生变化时,先会更新DOM。 - 接着,如果存在 `useLayoutEffect` ,那么这些钩子会在浏览器即将刷新屏幕之前立即被激活并运行其内部逻辑。 - 浏览器接着准备进行下一次重绘流程。 - 最终,任何由 `useEffect` 定义的操作将在当前帧结束后的下一个微任务间隙被执行。 因此可以得出结论:当涉及到同一级别的生命周期事件时(即初次加载或是后续的状态变化),`useLayoutEffect` 总是早于 `useEffect` 执行。 为了更直观地展示这一点,下面是一个简单的例子来比较两者的执行时间点差异: ```javascript import React, { useState, useEffect, useLayoutEffect } from 'react'; function Example() { const [count, setCount] = useState(0); console.log('Rendering...'); useLayoutEffect(() => { console.log('useLayoutEffect runs'); }, [count]); useEffect(() => { console.log('useEffect runs'); }, [count]); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } ``` 在这个案例里,每当点击按钮改变计数器数值的时候,“Rendering…” 将最先打印出来表示正在重新渲染组件;紧接着你会看到 "useLayoutEffect runs" 出现在控制台日志上,表明此时已经完成了所有必要的DOM变动但是还没有开始新的画面绘制过程;最后才是 "useEffect runs", 表明该阶段已处于两个连续的画面之间的一个短暂休息期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

www.www

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值