typescript 使用钩子从数组中删除对象(useState)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/57341541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Removing object from array using hooks (useState)
提问by collinswade408
I have an array of objects. I need to add a function to remove an object from my array without using the "this" keyword.
我有一个对象数组。我需要添加一个函数来从我的数组中删除一个对象,而不使用“this”关键字。
I tried using updateList(list.slice(list.indexOf(e.target.name, 1)))
. This removes everything but the last item in the array and I'm not certain why.
我尝试使用updateList(list.slice(list.indexOf(e.target.name, 1)))
. 这将删除数组中除最后一项之外的所有内容,我不确定为什么。
const defaultList = [
{ name: "ItemOne" },
{ name: "ItemTwo" },
{ name: "ItemThree" }]
const [list, updateList] = useState(defaultList);
const handleRemoveItem = e => {
updateList(list.slice(list.indexOf(e.target.name, 1)))
}
return (
{list.map(item => {
return (
<>
<span onClick={handleRemoveItem}>x </span>
<span>{item.name}</span>
</>
)}
}
)
EXPECTED: The clicked item will be removed from the list.
ACTUAL: The entire list gets removed, minus the last item in the array.
预期:单击的项目将从列表中删除。
ACTUAL:删除整个列表,减去数组中的最后一项。
Thanks in advance for any input!
提前感谢您的任何意见!
采纳答案by Cool Guy
First of all, the span
element with the click event needs to have a name
property otherwise, there will be no name to find within the e.target
. With that said, e.target.name
is reserved for form elements (input, select, etc). So to actually tap into the name property you'll have to use e.target.getAttribute("name")
首先,span
带有点击事件的元素需要有一个name
属性,否则在e.target
. 话虽如此,e.target.name
保留用于表单元素(输入、选择等)。所以要真正利用 name 属性,你必须使用e.target.getAttribute("name")
Additionally, because you have an array of objects, it would not be effective to use list.indexOf(e.target.name)
since that is looking for a string
when you are iterating over objects. That's like saying find "dog" within [{}, {}, {}]
此外,因为您有一个对象数组,所以使用它不会有效,list.indexOf(e.target.name)
因为它string
在您迭代对象时正在寻找 a 。这就像说在里面找到“狗”[{}, {}, {}]
Lastly, array.slice()
returns a new array starting with the item at the indexyou passed to it. So if you clicked the last-item, you would only be getting back the last item.
最后,array.slice()
返回一个新数组,从您传递给它的索引处的项目开始。因此,如果您单击最后一项,则只会返回最后一项。
Try something like this instead using .filter()
: codesandbox
尝试这样的事情而不是使用.filter()
:codeandbox
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = () => {
const defaultList = [
{ name: "ItemOne" },
{ name: "ItemTwo" },
{ name: "ItemThree" }
];
const [list, updateList] = useState(defaultList);
const handleRemoveItem = (e) => {
const name = e.target.getAttribute("name")
updateList(list.filter(item => item.name !== name));
};
return (
<div>
{list.map(item => {
return (
<>
<span name={item.name} onClick={handleRemoveItem}>
x
</span>
<span>{item.name}</span>
</>
);
})}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
回答by Will Jenkins
You can use Array.filterto do this in a one-liner:
您可以使用Array.filter以单行方式执行此操作:
const handleRemoveItem = name => {
updateList(list.filter(item => item.name !== name))
}
Eta: you'll also need to pass the name of your item in your onClick handler:
Eta:您还需要在您的 onClick 处理程序中传递您的项目名称:
{list.map(item => {
return (
<>
<span onClick={() =>handleRemoveItem(item.name)}>x </span>
<span>{item.name}</span>
</>
)}
回答by Mahesh Samudra
I just faced the same issue and fixed using the answers in this question. I'm putting my answer here because I had to use multiple answers to get there.
我刚刚遇到了同样的问题,并使用此问题中的答案进行了修复。我把我的答案放在这里是因为我必须使用多个答案才能到达那里。
const defaultList = [
{ name: "ItemOne" },
{ name: "ItemTwo" },
{ name: "ItemThree" }
]
const [list, updateList] = useState(defaultList);
const handleRemoveItem = idx => {
// assigning the list to temp variable
const temp = [...list];
// removing the element using splice
temp.splice(idx, 1);
// updating the list
updateList(temp);
}
return (
{list.map((item, idx} => {
return (
<div key={idx}>
<span onClick={() =>handleRemoveItem(idx)}>x </span>
<span>{item.name}</span>
</div>
)}
}
)
回答by Dimi Mikadze
You can use this function to remove an item from React's state array without mutating the state.
你可以使用这个函数从 React 的 state 数组中移除一个 item 而不会改变 state。
const handleRemoveItem = name => {
updateList(list => list.filter(item => item.name !== name));
}
Sandbox: https://codesandbox.io/s/ecstatic-goldwasser-76zop?fontsize=14
沙盒:https: //codesandbox.io/s/ecstatic-goldwasser-76zop?fontsize =14
回答by William Gunawan
I think this code will do
我认为这段代码会做
let targetIndex = list.findIndex((each) => {each.name == e.target.name});
list.splice(targetIndex-1, 1);
We need to check name value inside object so use findIndex instead. then cut the object start from target index to 1 array after target index.
我们需要检查对象内的名称值,因此请改用 findIndex。然后将对象从目标索引开始切割到目标索引后的 1 个数组。
From your comment your problem came from another part.
根据您的评论,您的问题来自另一部分。
Change this view section
更改此视图部分
return (
<>
<span onClick={() => handleRemoveItem(item) }>x </span>
<span>{item.name}</span>
</>
)}
change function handleRemoveItem format
更改函数handleRemoveItem格式
const handleRemoveItem = item => {
list.splice(list.indexOf(item)-1, 1)
updateList(list);
}
回答by Morphyish
This is because both sliceand splicereturn an array containing the removed elements.
这是因为slice和splice 都返回一个包含已删除元素的数组。
You need to apply a splice
to the array, and thenupdate the state using the method provided by the hook
您需要对splice
数组应用a ,然后使用钩子提供的方法更新状态
const handleRemoveItem = e => {
const newArr = [...list];
newArr.splice(newArr.findIndex(item => item.name === e.target.name), 1)
updateList(newArr)
}