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 以避免阻塞视觉更新。

相关推荐
永远的个初学者27 分钟前
图片优化 上传图片压缩 npm包支持vue(react)框架开源插件 支持在线与本地
前端·vue.js·react.js
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ28 分钟前
npm i / npm install 卡死不动解决方法
前端·npm·node.js
Kratzdisteln31 分钟前
【Cursor _RubicsCube Diary 1】Node.js;npm;Vite
前端·npm·node.js
杰克尼1 小时前
vue_day04
前端·javascript·vue.js
明远湖之鱼1 小时前
浅入理解跨端渲染:从零实现 React DSL 跨端渲染机制
前端·react native·react.js
悟忧2 小时前
规避ProseMirror React渲染差异带来的BUG
前端
小皮虾2 小时前
小程序云开发有类似 uniCloud 云对象的方案吗?有的兄弟,有的!
前端·javascript·小程序·云开发
Android疑难杂症2 小时前
鸿蒙Notification Kit通知服务开发快速指南
android·前端·harmonyos
T___T2 小时前
全方位解释 JavaScript 执行机制(从底层到实战)
前端·面试
阳懿2 小时前
meta-llama-3-8B下载失败解决。
前端·javascript·html