当前位置: 首页 > news >正文

【前端学习——react坑】useState使用

问题

使用useState 时,例如

const [selectedId, setSelectedId] = useState([false,true,false]);

这样直接利用,无法引发使用selectedId状态的组件的变化,但是selectedId是修改了的

 let temp=selectedId;temp[toggledId]=selectedId[toggledId]===false?true:false;setSelectedId(temp);

原因

一句话。let temp=selectedId;没有创建新的数组

这实际上是将 temp 设置为 selectedId 的引用,而不是一个新的数组。这意味着 temp 和 selectedId 共享相同的内存地址,它们指向相同的数组。所以,当你修改 temp 时,也会影响到 selectedId。

你直接修改了 selectedId 数组的值,React无法检测到setSelectedId前后状态的变化,因此不会触发 React 组件的重新渲染。

下面这个方法也不推荐,因为虽然 updatedSelectedId 这个数组是新的,但是其内部的元素本身与原数组 selectedId是相同的。因此,修改 updatedSelectedId[toggledId],其实是在修改原始的 selectedId对象。这样虽然会触发渲染,但是如果此时有另一个地方有着相同的初始 state,他们的 state 会被共享,也就是说你把本不该改变的状态也改变了。

  // 创建一个新的数组,保持不可变性const updatedSelectedId = [...selectedId];updatedSelectedId[toggledId] = !updatedSelectedId[toggledId];// 更新状态setSelectedId(updatedSelectedId);

解决

我们在更新state时要将state视为不可变的,你不应该使用类似于 arr[0] = ‘bird’ 这样的方式来重新分配数组中的元素,也不应该使用会直接修改原始数组的方法,例如 push() 和 pop()。可以通过使用像 filter() 和 map() 这样不会直接修改原始值的方法,从原始数组生成一个新的数组
在这里插入图片描述

其中数组展开运算符…还允许你把新添加的元素放在原始的 …artists 之。如此,展开操作就可以完成 push() 和 unshift() 的工作,将新元素添加到数组的末尾和开头。

因此这里我们通过map来产生新的数组

setMyList(selectedId.map((item,id)=> {if (id === toggledId) {return !item;} else {return item;}
}));

... 展开语法本质是是**“浅拷贝”——它只会复制一层**。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。

为什么在 React 中不推荐直接修改 state?

在这里插入图片描述

更新 state 中的数组

即使你拷贝了数组,你还是不能直接修改其内部的元素。这是因为数组的拷贝是浅拷贝——新的数组中依然保留了与原始数组相同的元素。因此,如果你修改了拷贝数组内部的某个对象,其实你正在直接修改当前的 state。

const nextList = [...list];
nextList[0].seen = true; // 问题:直接修改了 list[0] 的值
setList(nextList);

nextList 和 list 是两个不同的数组,nextList[0] 和 list[0] 却指向了同一个对象。因此,通过改变 nextList[0].seen,list[0].seen 的值也被改变了。

解决:可以使用 map 在没有 mutation 的前提下将一个旧的元素替换成更新的版本。

setMyList(myList.map(artwork => {if (artwork.id === artworkId) {// 创建包含变更的*新*对象return { ...artwork, seen: nextSeen };} else {// 没有变更return artwork;}
}));

相关文章:

  • 【AI基础】数据获取与整理、打标、增强方法、增强库imgaug
  • 【Linux】初识Linux和Linux环境配置
  • uniapp一些问题解决
  • 【国产中颖】SH79F9202U单片机驱动LCD段码液晶学习笔记
  • 第13章 层次式架构设计理论与实践
  • vs2013使用qt Linguist以及tr不生效问题
  • 用易查分制作研学活动报名,支持在线签名,一键导出报名统计表格!
  • java调用远程接口下载文件
  • 深度学习——卷积神经网络
  • 实战解析:爬取音乐每日推荐歌单并自动分享
  • TextFormField onSave 和onChange
  • 43-3 应急响应 - WebShell查杀工具
  • 三十、openlayers官网示例解析Double click, Drag and Zoom——第二次点击鼠标拖拽缩放地图效果、取消地图双击放大事件
  • Java中的super关键字详解
  • 探秘AI艺术:揭开Midjourney绘画的神秘面纱
  • create-react-app项目添加less配置
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ES2017异步函数现已正式可用
  • JS字符串转数字方法总结
  • leetcode-27. Remove Element
  • Mysql数据库的条件查询语句
  • Spring Cloud中负载均衡器概览
  • SQLServer之创建显式事务
  • 闭包--闭包之tab栏切换(四)
  • 当SetTimeout遇到了字符串
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 解决iview多表头动态更改列元素发生的错误
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 面试总结JavaScript篇
  • 如何解决微信端直接跳WAP端
  • 如何使用 JavaScript 解析 URL
  • 使用putty远程连接linux
  • 微信小程序实战练习(仿五洲到家微信版)
  • 想写好前端,先练好内功
  • 2017年360最后一道编程题
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #FPGA(基础知识)
  • $.ajax中的eval及dataType
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (办公)springboot配置aop处理请求.
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (算法设计与分析)第一章算法概述-习题
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .net MySql
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET多线程执行函数
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • @Transient注解
  • [ C++ ] STL---string类的模拟实现
  • []常用AT命令解释()
  • [《百万宝贝》观后]To be or not to be?