react-useState操作数组和对象的注意事项
LYT
首页
分类
标签
项目
留言
友链
关于

react-useState操作数组和对象的注意事项

2023年9月15日14时16分
2023年9月15日14时19分
前端
react useState
浏览量:
总浏览量:
0

react中useState常见对象和数组的解决方案

  不论在js还是ts中,数组和对象都是引用类型,直接赋值,传递的是变量的引用,所以在使用setState修改数组或者对象的值时候,要注意将变量进行拷贝!!!!

数组的解决方案

| | 避免使用(会改变原始数组) | 推荐使用(会返回一个新数组) | | -------- | -------------------------- | ---------------------------- | | 添加元素 | pushunshift | concat、[...,arr]展开语法 | | 删除元素 | popshiftsplice | filterslice | | 替换元素 | splice,arr[i]=...赋值 | map | | 排序 | reversesort | 先将数组复制一份 |

在后面追加

  在前面追加的方法同理。

import { useState } from "react" function App() { const [list,setList] = useState([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ setList([...list,{id:4,text:"ddd"}])//在后面追加元素 } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App

image-20230915142129579

在中间添加

import { useState } from "react" function App() { const [list,setList] = useState([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ // setList([...list,{id:4,text:"ddd"}])//在后面追加元素 setList([...list.slice(0,1),{id:4,text:'ddd'},...list.slice(1)]) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App

替换数组中某个元素

  注意在写tsx的过程中,要注意类型的匹配!,通过map方式遍历数组,改变数组的值以后返回的是一个新的数组。

import { useState } from "react" interface List{ id:number text:string } function App() { const [list,setList] = useState<List[]>([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ // setList([...list,{id:4,text:"ddd"}])//在后面追加元素 // setList([...list.slice(0,1),{id:4,text:'ddd'},...list.slice(1)]) setList(list.map((item):List=>{ if(item.id===2){ return {...item,text:"ddd"} } else{ return item } })) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App

拷贝的两种方式

浅拷贝

  使用浅拷贝反转数组。

import { useState } from "react" interface List{ id:number text:string } function App() { const [list,setList] = useState<List[]>([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ const cloneList = [...list] cloneList.reverse() setList(cloneList) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App

 不支持嵌套数组和对象的变化:当原始对象包含了嵌套的数组或对象,并且这些嵌套的数组或对象发生变化时,浅拷贝并不会触发对这些嵌套对象的拷贝。这意味着拷贝后的对象仍然会包含原始对象中的嵌套数组或对象的引用,而不是它们的独立副本。这可能导致无法实现预期的结果。

深拷贝

  首先需要安装一个第三方库

npm install @types/lodash

  同样实现反转数组的功能

对象的解决方案

修改单个属性

  通常使用的是浅拷贝的方式。.传播语法是的它只复制一层深的东西。这使它变得很快,但这也意味着如果你想更新一个嵌套的属性,你将不得不多次使用它。

import { useState } from "react" interface Info{ username:string age:number } export default function App(){ const [info,setInfo] = useState<Info>({ username:'lyt', age:22 }) function change(){ setInfo({ ...info, username:'liyatai' }) } return <div> <button onClick={change}>change</button><br /> {info.age} <br /> {info.username} </div> }

嵌套对象需要使用深拷贝

  如果对象的属性还有对象,那么浅拷贝就不方便了,这里可以用上文提到的深拷贝。

import { cloneDeep } from "lodash" import { useState } from "react" interface Info{ username:{ first:string last:string } age:number } export default function App(){ const [info,setInfo] = useState<Info>({ username:{ first:"Bruse", last:"Lee" }, age:22 }) function change(){ const cloneList = cloneDeep(info) cloneList.username.first="David" setInfo(cloneList) } return <div> <button onClick={change}>change</button><br /> {JSON.stringify(info)} </div> }

总结

  深拷贝看似很方便,但是在性能上是有缺陷的,而浅拷贝就有比较好的性能,所以使用哪种方式要根据具体的使用场景而定。