如何从 React 状态数组中删除组件而不删除数组的其余部分?
Posted
技术标签:
【中文标题】如何从 React 状态数组中删除组件而不删除数组的其余部分?【英文标题】:How do I delete a component from a React state array without deleting rest of array? 【发布时间】:2021-03-23 17:23:07 【问题描述】:我已经制作了一个基本的应用程序来练习 React,但我很困惑为什么当我尝试从状态数组中删除单个组件时,它之后的所有项目也会被删除。这是我的基本代码:
App.js:
import React from 'react'
import Parent from './Parent';
import './App.css';
function App()
return (
<div className="App">
<Parent />
</div>
);
export default App;
Parent.js:
import React, useState from 'react';
import ListItem from './ListItem';
import './App.css';
function Parent()
const [itemList, setItemList] = useState([])
const [numbers, setNumbers] = useState([])
const addItem = () =>
const id = Math.ceil(Math.random()*10000)
const newItem = <ListItem
id=id
name='Item-' + id
deleteItem=deleteItem
/>
const list = [...itemList, newItem]
setItemList(list)
;
const deleteItem = (id) =>
let newItemList = itemList;
newItemList = newItemList.filter(item =>
return item.id !== id
)
setItemList(newItemList);
const addNumber = () =>
const newNumbers = [...numbers, numbers.length + 1]
setNumbers(newNumbers)
const deleteNum = (e) =>
let newNumbers = numbers
newNumbers = newNumbers.filter(n => n !== +e.target.innerhtml)
setNumbers(newNumbers);
return (
<div className="Parent">
List of items:
<div>
itemList
</div>
<button onClick=addItem>
Add item
</button>
<div>
List of numbers:
<div>
numbers.map(num => (
<div onClick=deleteNum>num</div>
))
</div>
</div>
<button onClick=addNumber>
Add number
</button>
</div>
);
;
export default Parent;
ListItem.js:
import React from 'react';
import './App.css';
function ListItem(props)
const id, name, deleteItem = props;
const handleDeleteItem = () =>
deleteItem(id);
return (
<div className="ListItem" onClick=handleDeleteItem>
<div>name</div>
</div>
);
;
export default ListItem;
-
当我通过单击按钮添加项目时,父状态会正确更新。
当我单击项目(删除它)时,它会删除自身,但也会删除数组中出现在它之后的每个项目
我也用数字对其进行了测试(不是创建单独的组件)。这些删除正确 - 仅删除我单击的单个数字。
据我所知,各个项目组件正在保存有关创建它们时父状态值的引用。这对我来说似乎是非常奇怪的行为......
当 itemList 状态数组由单独的组件组成时,如何仅删除单个项目?
谢谢
编辑:根据 Bergi 的说明,我通过将“itemList”状态值转换为要在列表更改时渲染(和重新渲染)的对象数组来解决此问题:
const addItem = () =>
const id = Math.ceil(Math.random()*10000);
const newItem =
id: id,
name: 'Item-' + id,
const newList = [...itemList, newItem]
setItemList(newList)
...
React.useEffect(() =>
, [itemList]);
...
<div className="Parent">
List of items:
<div>
itemList.map(item =>
return (<ListItem
id=item.id
name=item.name
deleteItem=deleteItem
/>);
)
...
【问题讨论】:
不要使用Math.ceil(Math.random()*10000)
作为ID,而是使用itemList.length
这样会导致以后要删除多个项目:1)创建5个项目(id分别为0、1、2、3、4)——2)删除第3个项目(id 2) -- 3) 再添加两个项目(id 现在是 0、1、3、4、4、5)
【参考方案1】:
问题在于您的deleteItem
函数是旧itemList
的闭包,从创建项目的那一刻开始。两种解决方案:
setItemList
的回调形式
不要在该列表中存储 react 元素,而只是简单的对象(您可以将其用作道具)并仅在渲染 ListItem
s 时传递(最新的)deleteItem
函数
【讨论】:
谢谢Bergi,已经解决了!仅供参考,我使用了普通对象方法。我会为遇到同样问题的其他人更新我的原始帖子。以上是关于如何从 React 状态数组中删除组件而不删除数组的其余部分?的主要内容,如果未能解决你的问题,请参考以下文章