【react】useEffect与useLayoutEffect
useEffect与useLayoutEffect
相关文章
- 浅谈react fiber架构
- 为什么说只能在最顶层使用 Hook
- useEffect与useLayoutEffect
- react hooks是什么
- react 生命周期
- react 15-16架构变化
- react 通信方式
- react api
- 为什么 React 渲染列表时需要加上 key
useEffect与useLayoutEffect
一、两者的区别
调用时机:
useEffect:useEffect 在组件渲染后(包括首次渲染和后续更新)异步执行,不会阻塞浏览器渲染。
useLayoutEffect:useLayoutEffect 会在所有 DOM 变更之后同步执行,但在浏览器绘制之前。因此,它的执行时机比 useEffect 更早,可能会阻塞浏览器的渲染。
详细
- 当元件被加入时 (mount),useEffect和useLayoutEffect 会被第一次执行。
- 当每次元件重新渲染时,如果 dependencies 的值有改变,先将旧的 props 和 state 执行 cleanup function,再带着新- 的 props 和 state 执行 setup function。
- cleanup function 的代码,会在元件生命周期结束 (unmount) 时,执行最后一次。
影响性能:
- useEffect:由于 useEffect 是异步执行的,它不会阻塞浏览器的渲染,因此对于大多数副作用操作来说,它是更好的选择,可以避免影响页面的响应性能。
- useLayoutEffect:因为 useLayoutEffect 是同步执行的,它可能会阻塞浏览器的渲染,因此在处理大量或计算密集型的操作时,可能会影响页面的性能表现。
适用场景:
- useEffect:适用于大多数情况下,特别是涉及网络请求、数据订阅、DOM 操作等不需要同步执行的副作用操作。
- useLayoutEffect:适用于需要在浏览器绘制之前立即执行的操作,比如需要测量 DOM 元素尺寸、获取布局信息等。通常情况下,应该谨慎使用 useLayoutEffect,确保不会影响页面的性能。
二、示例
1 |
|
当我们执行上方代码时,连续点击 div 区块,会看到画面产生闪烁。
原因是,当你每次点击 div,此时 count 会被更新为 0,画面会重新渲染变为 0,同时,因为 count 被更新,也会触发 useEffect 执行。所以在重绘完成之后, useEffect 执行并把 count 更新为另一串随机数字,画面也会再渲染一次,因为两次渲染时间很快,所以造成闪烁。
假设我们把上方代码的useEffect 换成useLayoutEffect,当你每次点击 div,此时 count 会被更新为 0,但这时,画面不会被重新渲染变为 0,而是先等待 useLayoutEffect 内的代码执行完毕之后,state 已经更新为新的随机数字,这时画面才进行重绘。
三、如何dependencies为空,useEffect和useLayoutEffect 什么时候会执行?
此 effect 会是在每次重新渲染元件后重新执行
四、如果 dependencies 中有 object 会怎么样?
下方代码的 options 物件会在元件每次重新渲染时,都是不同的物件,所以这个 useEffect 可能会在每次渲染时都重新执行,因为在 dependencies 中的 options 有改变。
1 |
|
如果要避免上方代码造成不必要触发 useEffect,其实可以把动态的物件放在 Effect 中,并把 dependencies 中的物件改为 string 或 number,如下。
1 |
|
五、什么时候使用 useLayoutEffect?
当需要在浏览器绘制之前立即执行的操作时,比如需要测量 DOM 元素尺寸、获取布局信息等,可以使用 useLayoutEffect。以下是一些可能的示例:
获取元素尺寸
1 |
|
在这个例子中,我们有一个组件,它包含一个 div 元素,并且我们想要获取这个 div 元素的宽度。我们使用了 useLayoutEffect 来确保在元素被渲染到 DOM 后立即获取其尺寸,然后更新组件的状态以显示宽度。这样,我们就可以在浏览器绘制之前得到最新的布局信息。
如果改为useEffect,则会渲染两次,第一次宽度是0,第二次才是真实测量的值。
调整布局
1 |
|
在这个例子中,我们有一个组件,它包含一个按钮和一个条件渲染的元素。当点击按钮时,元素将变为可见状态。我们使用 useLayoutEffect 来确保在元素变为可见状态时,浏览器会立即滚动到页面顶部,以确保用户可以立即看到该元素。这样,我们就可以在浏览器绘制之前执行必要的布局调整操作。
如果改为useEffect,滚动条则会肉眼可见的滚动。