在组件状态下从数组中删除元素

我试图找到最好的方法来删除一个元素从一个组件的状态数组。既然我不应该直接修改 this.state变量,那么有没有比这里更好的方法(更简洁)从数组中删除元素呢?:

  onRemovePerson: function(index) {
this.setState(prevState => { // pass callback in setState to avoid race condition
let newData = prevState.data.slice() //copy array from prevState
newData.splice(index, 1) // remove element
return {data: newData} // update state
})
},

谢谢你。

更新

这已更新为在 setState 中使用回调。在更新当前状态时引用当前状态时应该这样做。

127633 次浏览

您可以使用 来自 ABC1的 update()不变性助手,它在引擎盖下有效地执行相同的操作,但是您正在执行的操作是正确的。

this.setState(prevState => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))

我所见过的最干净的方法是使用 filter:

removeItem(index) {
this.setState({
data: this.state.data.filter((_, i) => i !== index)
});
}

下面是使用 ES6扩展语法从处于状态的数组中删除元素的方法。

onRemovePerson: (index) => {
const data = this.state.data;
this.setState({
data: [...data.slice(0,index), ...data.slice(index+1)]
});
}

这里有一个简单的方法:

removeFunction(key){
const data = {...this.state.data}; //Duplicate state.
delete data[key];                  //remove Item form stateCopy.
this.setState({data});             //Set state as the modify one.
}

希望有帮助! ! !

我相信在 setState()中引用 this.state是不被鼓励的(状态更新可能是异步的)。

文档建议使用带有回调函数的 setState(),这样当更新发生时 preState 就可以在运行时传入。看起来是这样的:

使用不带 ES6的 Array.Prototype.filter

removeItem : function(index) {
this.setState(function(prevState){
return { data : prevState.data.filter(function(val, i) {
return i !== index;
})};
});
}

在 ES6箭头函数中使用 Array.Prototype.filter

removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i !== index)
}));
}

使用不可变性助手

import update from 'immutability-helper'
...
removeItem(index) {
this.setState((prevState) => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
}

使用扩展

function removeItem(index) {
this.setState((prevState) => ({
data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
}))
}

注意,在每个实例中,不管使用什么技术,this.setState()都会被传递一个回调函数,没有是对旧 this.state的一个对象引用;

正如在对 ephrion 上述答案的注释中所提到的,filter ()可能比较慢,特别是对于大型数组,因为它循环查找似乎已经确定的索引。这是一个干净但效率低下的解决方案。

作为一种替代方法,我们可以简单地“切割”出所需的元素,然后将这些片段连接起来。

var dummyArray = [];
this.setState({data: dummyArray.concat(this.state.data.slice(0, index), this.state.data.slice(index))})

希望这个能帮上忙!

如果要删除元素(不带索引) ,可以使用此函数

removeItem(item) {
this.setState(prevState => {
data: prevState.data.filter(i => i !== item)
});
}

我想在这里插一句,即使这个问题已经是 正确答案是@pscl,以防其他人遇到同样的问题,我做了。在这4种方法中,我选择使用带箭头函数的 es6语法,因为它简洁而且不依赖于外部库:

在 ES6箭头函数中使用 Array.Prototype.filter

removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i != index)
}));
}

正如您所看到的,我做了一个小小的修改,忽略了索引的类型(从 !==!=) ,因为在我的例子中,我是从字符串字段检索索引的。

如果在客户端删除一个元素时看到奇怪的行为,另一个有用的地方是 永远不要使用数组的索引作为元素的键:

// bad
{content.map((content, index) =>
<p key={index}>{content.Content}</p>
)}

当 React 与更改的虚拟 DOM 不同时,它将查看键以确定更改了什么。所以如果你使用了索引数组中少了一个它会删除最后一个。相反,使用内容的 id 作为键,如下所示。

// good
{content.map(content =>
<p key={content.id}>{content.Content}</p>
)}

以上内容摘自 这个答案来自一个相关的帖子

编码愉快,各位!

您可以使用一行 helper 函数使代码更具可读性:

const removeElement = (arr, i) => [...arr.slice(0, i), ...arr.slice(i+1)];

然后像这样使用它:

this.setState(state => ({ places: removeElement(state.places, index) }));

只是一个建议,在您的代码中,而不是使用 let newData = prevState.data,您可以使用扩展,这是在 ES6中引入的,即您可以使用 let newData = ...prevState.data 复制数组

三个点... 代表 传播算子或者 休止参数,

它允许一个数组表达式或字符串或任何可以迭代的东西在需要零个或多个函数调用参数或数组元素参数的地方展开。

此外,还可以通过以下方法从数组中删除项

onRemovePerson: function(index) {
this.setState((prevState) => ({
data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
}))
}

希望这个有用! !