1. 前言
- 碰巧今天面试
react
,问到这个问题(useEffect 和 useLayoutEffect有啥区别),都在射程范围内,那就来捋一捋
2. 是什么 what
-
useEffect
和 useLayoutEffect
是 React 提供的两个副作用
钩子函数,用于在函数式组件中处理副作用操作
3. useEffect:
- useEffect 在组件
渲染完成后
执行,通常用于处理副作用操作,如数据获取、订阅事件、定时器等。
- useEffect 的回调函数会在每次
渲染结束后
异步执行,不会阻塞
浏览器的渲染过程。
- useEffect 的回调函数可以
返回
一个清理函数
,用于清除副作用操作,比如取消订阅、清除定时器等。
- useEffect 的执行时机是在浏览器完成
绘制后
,对用户来说是不可见的。
4. useLayoutEffect:
- useLayoutEffect 在组件
渲染完
成后,浏览器绘制之前
执行,可以看作是 useEffect 的同步
版本。
- useLayoutEffect 的回调函数会在每次渲染
结束后
同步执行,会阻塞
浏览器的渲染
过程,可能导致页面性能下降。
- useLayoutEffect 的回调函数也可以
返回
一个清理函数
,用于清除副作用操作。
- useLayoutEffect 的执行时机是在浏览器完成
绘制前
,对用户来说是可见的。
5. useEffect 与 useLayoutEffect 对比 demo
import React, { useEffect, useLayoutEffect, useState } from 'react';
const Demo = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('useEffect');
document.title = `Count: ${count}`;
}, [count]);
useLayoutEffect(() => {
console.log('useLayoutEffect');
// 模拟一个耗时操作
for (let i = 0; i < 1000000000; i++) {
// Do something
}
document.title = `Count: ${count}`;
}, [count]);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default Demo;
- 先打印了 useEffect,然后是 useLayoutEffect。
- 这是因为
useLayoutEffect
在更新 DOM 前同步
执行,可能会导致页面渲染的卡顿
。
- 而
useEffect
在页面渲染完成后异步
执行,不会阻塞
页面的渲染
6. 表格对比
|
useEffect |
useLayoutEffect |
调用时机 |
组件渲染完成后异步执行 |
组件渲染完成后同步执行 |
执行时机 |
浏览器完成绘制后,对用户来说不可见 |
浏览器绘制前,对用户来说可见 |
阻塞渲染 |
不会阻塞浏览器的渲染过程 |
会阻塞浏览器的渲染过程 |
副作用操作 |
适用于大多数副作用操作 |
适用于需要立即执行、对布局有影响的副作用操作 |
清理函数 |
可以返回一个清理函数,用于清除副作用操作 |
可以返回一个清理函数,用于清除副作用操作 |
使用建议 |
在大多数情况下使用 useEffect
|
在需要同步执行、对布局有影响的情况下使用 useLayoutEffect
|
底层函数 |
调用的 mountEffectImpl方法 |
调用的 mountEffectImpl方法,在使用上也没什么差异,基本可以直接替换 |
- 虽然
useLayoutEffect
在某些情况下可能会导致页面性能下降,
但它在某些特定的场景下是非常有用的,例如在需要准确获取元素尺寸、计算布局等情况下。
- 在大多数情况下,使用
useEffect
是更安全和更推荐的选择。
参考资料
初心
我所有的文章都只是基于入门,初步的了解;是自己的知识体系梳理,如有错误,道友们一起沟通交流;
如果能帮助到有缘人,非常的荣幸,一切为了部落
的崛起;
共勉
网友评论