从组件状态中的数组中删除元素

时间:2015-04-08 23:58:50

标签: javascript reactjs

我正在尝试找到在组件状态下从数组中删除元素的最佳方法。既然我不应该直接修改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中使用回调。这应该在更新时引用当前状态时完成。

11 个答案:

答案 0 :(得分:118)

我见过的最简洁的方法是使用filter

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

答案 1 :(得分:86)

你可以使用update() immutability helper from react-addons-update,它有效地做同样的事情,但你正在做的事情很好。

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

答案 2 :(得分:55)

我认为不鼓励在setState()内引用setState() np.insert

文档建议将removeItem : function(index) { this.setState(function(prevState){ return { data : prevState.data.filter(function(val, i) { return i !== index; })}; }); } 与回调函数一起使用,以便在更新发生时在运行时传入prevState。所以这就是它的样子:

使用不带ES6的Array.prototype.filter

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

将Array.prototype.filter与ES6箭头函数一起使用

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

使用immutability-helper

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

使用点差

this.setState()

请注意,在每个实例中,无论使用何种技术,this.state都会传递回调,是对旧uuid的对象引用;

答案 3 :(得分:22)

这是一种使用ES6扩展语法从状态中删除元素的方法。

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

答案 4 :(得分:2)

我想在这里说话,即使这个问题已经answered correctly by @pscl,以防其他人遇到同样的问题。在4种方法中,我选择将es6语法与箭头函数一起使用,因为它简洁且缺乏对外部库的依赖:

将Array.prototype.filter与ES6箭头函数一起使用

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>
)}

以上内容摘自this answer from a related post

快乐的编码每个人!

答案 5 :(得分:1)

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

作为替代方案,可以简单地“切片”。输出所需的元素并连接片段。

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

希望这有帮助!

答案 6 :(得分:1)

如果要删除元素(不带索引)

,可以使用此功能
removeItem(item) {
  this.setState(prevState => {
    data: prevState.data.filter(i => i !== item)
  });
}

答案 7 :(得分:0)

您可以使用一行帮助功能使代码更具可读性:

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

然后像这样使用它:

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

答案 8 :(得分:0)

仅是建议,您可以在代码中代替使用let newData = prevState.data,而可以使用ES6中引入的传播,即可以使用let newData = ...prevState.data 复制数组

三个点...代表Spread OperatorsRest Parameters

它允许将数组表达式或字符串或任何可以迭代的内容扩展到期望零个或多个函数调用参数或数组元素的地方。

另外,您可以使用以下命令从数组中删除项目

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

希望这会有所帮助!

答案 9 :(得分:-2)

我正在使用它,希望它没有问题和帮助。

removeItem(item){
    const index = this.state.yourArray.indexOf(item);
    if (index < 0) return
    this.state.yourArray.splice(index, 1)
    this.setState({yourArray: this.state.yourArray})
}

答案 10 :(得分:-3)

这是一种简单的方法:

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.
}

希望它能帮助!!!

相关问题