React Hooks:Effect无限回调踩坑

2023-11-16

场景

我的目的是通过Effect来模拟组件的componentDidMount,在渲染完成之后,通过setTimeout来处理操作,向keyIndex中push一个新的元素,并更新keyIndex,但是这个操作我确定只会执行一次。
错误代码如下:

  const [keyIndex, setKeyIndex] = React.useState([]);
  React.useEffect(() => {
  		setTimeout(() => {
  		console.log('err log')
      	let array = [].concat(keyIndex);
		let key = timeLine[0].id;
     	 array.push(key);
     	 setKeyIndex(array)
     	 },2000);
  }, [setKeyIndex]);

代码中我加了一句console.log('err log') ,在组件被执行之后,控制台无限输出err log

问题原因

在Hooks中,虽然可以通过向useEffect传递第二个参数(此处我是在结尾传递了[setKeyIndex]),来达到在传递的数组没有变化时,不对组件进行render操作。
但是这个第二个参数是有限制的—这里的问题就是,第二个参数是引用类型

什么是引用类型:

  • 值类型(基本类型):数值(number)、布尔值(boolean)、null、undefined、string(在赋值传递中会以引用类型的方式来处理)。
  • 引用类型:对象、数组、函数。

根源

useEffect会比较前一次渲染和后一次渲染的值,即使两个值在数值上是相等的,但是在堆栈中对应的地址并不相同,所以 === 操作的时候,值肯定为false。所以引用类型比较不出来数据的变化,会不停地得到false值,并对组件进行render,造成死循环。

解决方法

  • useRef
	const keyIndexRef = useRef(keyIndex);
 	keyIndexRef.current = keyIndex;

通过useRef,将keyIndex数据绑定到keyIndexRef.current上,此时的keyIndexRef是一个可变值盒子,他自身都是可以被更改的。useRef的特点是会在每次渲染时返回同一个 ref 对象,这就解决了我们的render前后数据始终不会相等(===)的问题。

在我这里,修改后的代码如下:

React.useEffect(() => {
    setTimeout(() => {
      let array = [].concat(keyIndexRef.current);
      let key = timeLine[0].id;
      array.push(key);
      setKeyIndex(array);
      });
   },[])
  • 通过setData 接收函数作为参数,并利用闭包和参数来实现数据更新
    用一个类似的例子来进行举例
const [flag, setFlag] = useState(false);
function dealClick() {
        setFlag(!flag);

        setTimeout(() => {
            setFlag(flag => !flag);
        }, 2000);
    }
return (
        <button onClick={dealClick}>{flag ? "true" : "false"}</button>
    );

另外,如果useEffect不放置任何参数,则在组件化的过程中会且仅执行一次。但是如果还是出现改变引用类型的错误的话,每次执行都会拿到的keyIndex的默认初始值,实际setKeyIndex 的结果并不会被更新上去

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Hooks:Effect无限回调踩坑 的相关文章

  • 手机通过RNDIS共享网络

    RNDIS 是 Remote Network Driver Interface Specification 远程网络驱动程序接口规范 的首字母缩写 实际上的作用为 TCP IP over USB 也即把 USB 设备 如手机 作为网卡 是基
  • 用Java开发贪食蛇小游戏

    用Java开发贪食蛇小游戏 一 实验内容 1 实现贪吃蛇游戏基本功能 屏幕上随机出现一个 食物 称为豆子 上下左右控制 蛇 的移动 吃到 豆子 以后 蛇 的身体加长一点 得分增加 蛇 碰到边界或 蛇头与蛇身相撞 蛇死亡 游戏结束 为游戏设计
  • Unity3D实现游戏暂停

    Unity3D实现游戏暂停 要素理解 代码 分析理解 要素理解 timeScale Float 默认值为1 能够影响时间流速 置0可使时间暂停 查阅官网文档 Time timeScale 中可以发现对于timeScale描述中要求暂停物体的
  • Hdu 1240 Asteroids题解

    题目链接 1240 思路 BFS搜索 采用队列实现 搜索的层级即为步数 代码如下 include
  • Linux虚拟环境安装cuda、cudnn、pytorch

    来自http t csdn cn WSvvX 1 创建虚拟环境 conda create n environment name 激活虚拟环境 conda cactivate environment name 2 安装cuda 首先查出源内所

随机推荐

  • 【Java】自建IOS应用(IPA)发布服务器

    简单描述一下总的过程 在某个后台上 版本发布平台 上传原始的ipa文件 解析ipa 主要是解析info plist 从中获取软件名 版本 icons等 解析embedded mobileprovision 获取证书过期时间 生成一个新的pl
  • 【限时免费】20天拿下华为OD笔试之【单调栈】2023Q1A-找朋友【欧弟算法】全网注释最详细分类最全的华为OD真题题解

    单调栈 2023Q1A 找朋友 题目描述与示例 题目描述 在学校中 N 个小朋友站成一队 第 i 个小朋友的身高为 height i 第 i 个小朋友可以看到的右边的第一个比自己身高更高的小朋友 j 那么 j 是 i 的好朋友 j gt i
  • SSH登录步骤

    SSH登录格式 ssh 用户名 ip地址 回车 比如 ssh root 0 0 0 1 如果需要切换用户 su 用户名 比如 su test1 从普通用户切换到root用户 可以使用sudo su 或 su
  • ingress是什么

    ingress是什么 需求 概念 详细说明 Ingress和Service的区别 注意点 需求 每个Service都要有一个负载均衡服务 所以这个做法实际上既浪费成本又高 作为用户 更希望看到Kubernetes为我内置一个全局的负载均衡器
  • 怎么制作睡袋rust_怎么不花钱自己在野外制作吊床—户外手工技能(吊床露营的好处)...

    当你想到露营的时候 你会想到什么形象 可能是帐篷 几十年来 帐篷和露营旅行确实已经密不可分 但最近这种感觉已经开始发生变化 因为出现了另一种露营方式 吊床 这样的吊床在中美洲和南美洲已经很常见了 但现在在设计和材料上经历了许多进步 越来越受
  • C#开发---Aspose.Word操作Word文档(一)

    目录 1 书签赋值 2 新起一行添加文本 3 查找文档内标题 4 往pdf中插入目录 1 书签赋值 提前创建好word文档 插入书签 在程序中给书签赋值
  • linux编程获取本机IP地址

    getifaddrs 和struct ifaddrs的使用 获取本机IP 博客分类 Linux C编程 ifaddrs结构体定义如下 C代码 struct ifaddrs struct ifaddrs ifa next Next item
  • VMware Ubuntu安装详细过程(详细图解)

    说明 该篇博客是博主一字一码编写的 实属不易 请尊重原创 谢谢大家 一 下载Ubuntu镜像文件 下载地址 http mirrors aliyun com ubuntu releases 16 04 进入下载页面 如下图选择版本点击即可下载
  • Android NDK 编译时出现make (e=2): 系统找不到指定的文

    今天编译一个so文件时出现如下错误 C Users xxj Desktop test OpenCamera gt ndk build armeabi v7a Compile SeetafaceSo lt face detection cpp
  • java中访问修_Java中常见的访问/非访问修饰符

    Java中常见的访问 非访问修饰符 Java中常见的访问 非访问修饰符 1 Java中有下列常见访问修饰符 private 私有变量和方法 非外部类 只能被声明它们的类的实例所使用 default 类中的数据 方法和它本身能够被声明为默认d
  • 如何新建Quartus工程—FPGA入门教程

    这一章我们来实现第一个FPGA工程 LED流水灯 我们将通过流水灯例程向大家介绍一次完整的FPGA开发流程 从新建工程 代码设计 综合实现 管脚约束 下载FPGA程序 掌握本章内容 大家就算正式的开始入门FPGA开发了 1 1 2 新建工程
  • 老Java程序员花两天做了个消消乐(天天爱消除)

    老Java程序员花两天做了个消消乐 天天爱消除 引言 一直就想做一个消消乐 这次正好找到了素材 就自己琢磨写了一个 我觉得这个游戏难点就在消除 以及消除后的下落 其他的地方也就还好 这次做完了写个文章大家唠一波 效果图 实现思路 1 绘制窗
  • PostgreSQL

    PostgreSQL 是一个免费的对象 关系数据库服务器 ORDBMS 在灵活的BSD许可证下发行 PostgreSQL 开发者把它念作 post gress Q L PostgreSQL 的 Slogan 是 世界上最先进的 开源关系型数
  • VMware16虚拟机安装及配置(保姆级教程),这一篇就够了

    1 虚拟机VMware的下载官网地址 https www vmware com cn html VMware 安装 1 打开下载好的 exe 文件 即可开始安装 2 点击下一步 3先勾选我接受许可协议中的条款 然后点击下一步 4 自定义安装
  • 05-----撤销add,commit,push的方法(包括如何删除已经push到远程库的单个文件或者文件夹)

    1 撤销add添加的多余文件 git reset filename 撤销add到缓冲区的部分文件 2 撤销commit的多余文件 git log 先使用查看已经提交的commitId节点 git reset commit id 回退到上一个
  • 为什么我选用了springcloud而不是dubbo

    写好的代码越来越满足不了需求 因为需求总是在不断的变化 在技术选型时 实在是心有余而力不足 思来想去 就考虑了使用微服务架构来实现 功能模块化 今天主要讲讲为什么需要微服务架构 还是以故事的形式呈现 一 认识微服务 阶段一 单体服务 话说小
  • C语言密码破译

    请用C语言编程序将 China 译成密码 密码规律是 用原来的字母后面第4个字母代替原来的字母 例如 字母 A 后面第4个字母是 E 用 E 代替 A 因此 China 应译为 Glmre 请编一程序 用赋初值的方法使 cl c2 c3 c
  • IntelliJ IDEA(编码篇):集成Junit4插件,快速生成测试类

    目录 安装JUnitGenerator V2 0 修改JUnitGenerator V2 0的配置 生成JUnit4测试用例 注意 安装JUnitGenerator V2 0 1 通过网络安装 如下 2 手动下载插件安装 插件下载 http
  • 全网最简单解决方式1045-Access denied for user root@localhost(using password:YES)

    最近 Javaweb小学期 和 数据库小学期 答辩 极限赶大作业 唉 1045 Access denied for user root localhost using password YES 连接数据库时出现了这个问题 网上大概有3种解决
  • React Hooks:Effect无限回调踩坑

    场景 我的目的是通过Effect来模拟组件的componentDidMount 在渲染完成之后 通过setTimeout来处理操作 向keyIndex中push一个新的元素 并更新keyIndex 但是这个操作我确定只会执行一次 错误代码如