react18中的useEffect和useLayoutEffect的原理分析

useEffect 是 React 中用于处理副作用的函数。它可以在组件渲染后执行一些额外的操作,例如发送网络请求、更新 DOM 等。

useEffect 的基本语法如下:

js 复制代码
useEffect(() => {
  // 副作用代码
}, [依赖项]);

其中,第一个参数是一个回调函数,会在组件渲染后执行;第二个参数是一个数组,表示该副作用函数所依赖的变量或状态。如果第二个参数为空数组,则该副作用函数只会在组件第一次渲染时执行一次。如果第二个参数包含某个变量或状态,则该副作用函数会在该变量或状态发生变化时重新执行。

不带依赖项的 useEffect 示例:

  • 只要组件渲染时执行一次
js 复制代码
useEffect(() => {
  // 副作用代码
});

useEffect 依赖项为空数组的示例:

  • 初始化时执行一次
js 复制代码
useEffect(() => {
  // 副作用代码
}, []);

useEffect 依赖项有值时的示例:

  • a, b, c, d 任意一个值变化时执行
js 复制代码
useEffect(() => {
  // 副作用代码
}, [a, b, c, d]);

useEffect中,我们可以使用async/await语法来处理异步操作。例如:

js 复制代码
useEffect(async () => {
  const result = await fetch("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  const data = await result.json();
  console.log("🚀 ~ useEffect ~ data:", data);
  return () => {}; // 返回一个清理函数,否则就会报错
}, []);

因为useEffect要返回的函数是清理函数,当我们在 callback 前面加上 async,返回了一个 promise,这个时候就需要返回一个清理函数,否则会报错。

或者可以这样写

js 复制代码
const getData = async () => {
  const result = await fetch("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  const data = await result.json();
  console.log("🚀 ~ useEffect ~ data:", data);
  return data;
};
getData();

清除函数的副作用,比如在组件卸载时清除定时器,且在里面函数里面获取的状态是上次更新的状态,不是当前最新的值,所以需要使用 useRef 保存状态

js 复制代码
useEffect(async () => {
  const [count, setCount] = useState(0);
  return () => {
    console.log(count)
}, []);

useEffect 的原理

函数组件在渲染(或更新)期间,遇到 useEffect 操作,会基于 MountEffect 方法把 callback(和依赖项)加入到 effect 链表中!

在视图渲染完毕后,基于 UpdateEffect 方法,通知链表中的方法执行!

1、按照顺序执行期间,首先会检测依赖项的值是否有更新「有容器专门记录上一次依赖项的值」;有更新则把对应的 callback 执行,没有则继续处理下一项!!

2、遇到依赖项是空数组的,则只在第一次渲染完毕时,执行相应的 callback

3、遇到没有设置依赖项的,则每一次渲染完毕时都执行相应的 callback

useLayoutEffect 的原理

其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。

可以使用它来读取 DOM 布局并同步触发重渲染。

在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

尽可能使用标准的 useEffect 以避免阻塞视觉更新。

相关推荐
小飞侠在吗5 小时前
vue props
前端·javascript·vue.js
DsirNg7 小时前
页面栈溢出问题修复总结
前端·微信小程序
小徐_23337 小时前
uni-app 也能远程调试?使用 PageSpy 打开调试的新大门!
前端·微信小程序·uni-app
大怪v7 小时前
【Virtual World 03】上帝之手
前端·javascript
别叫我->学废了->lol在线等8 小时前
演示 hasattr 和 ** 解包操作符
开发语言·前端·python
霍夫曼9 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
DARLING Zero two♡9 小时前
浏览器里跑 AI 语音转写?Whisper Web + cpolar让本地服务跑遍全网
前端·人工智能·whisper
Lovely Ruby9 小时前
前端er Go-Frame 的学习笔记:实现 to-do 功能(三),用 docker 封装成镜像,并且同时启动前后端数据库服务
前端·学习·golang
深红9 小时前
玩转小程序AR-实战篇
前端·微信小程序·webvr
银空飞羽9 小时前
让Trae SOLO全自主学习开发近期爆出的React RCE漏洞靶场并自主利用验证(CVE-2025-55182)
前端·人工智能·安全