什么是在ReactJS中更新数组中对象的最佳方法?

Ale*_*ack 48 javascript reactjs

如果你有一个数组作为你的状态的一部分,并且该数组包含对象,那么通过更改其中一个对象来更新状态是一种简单的方法吗?

示例,从反馈教程中修改:

var CommentBox = React.createClass({
  getInitialState: function() {
    return {data: [
      { id: 1, author: "john", text: "foo" },
      { id: 2, author: "bob", text: "bar" }
    ]};
  },
  handleCommentEdit: function(id, text) {
    var existingComment = this.state.data.filter({ function(c) { c.id == id; }).first();
    var updatedComments = ??; // not sure how to do this  

    this.setState({data: updatedComments});
  }
}
Run Code Online (Sandbox Code Playgroud)

Not*_*ple 47

我非常喜欢用Object.assign而不是不变的助手来做这件事.

handleCommentEdit: function(id, text) {
    this.setState({
      data: this.state.data.map(el => (el.id === id ? Object.assign({}, el, { text }) : el))
    });
}
Run Code Online (Sandbox Code Playgroud)

我只是认为这比拼接更简洁,并且不需要知道索引或明确处理未找到的情况.

如果你感觉所有ES2018,你也可以用传播而不是 Object.assign

this.setState({
  data: this.state.data.map(el => (el.id === id ? {...el, text} : el))
});
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,谢谢!由于 _you 不应该访问 setState_ 中的状态,因此这是一个更安全的版本: `this.setState(prevState => ({ data: prevState.data.map(el => (el.id === id ? { . ..el,文本 } : el)) }))` (4认同)
  • 愿力量与你同在@Luke。这很整洁。 (2认同)
  • 喜欢您的解决方案:简短且不依赖第三方库。 (2认同)
  • @user3884753 `{text}` 是 `{text: text}` 的简写。由于“text”被定义为变量,因此您可以将其用作对象中的名称和值,而无需定义两次。它随 ES6 一起提供,有时被称为“[简写属性名称](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#new_notations_in_ecmascript_2015)” (2认同)

nil*_*gun 37

在更新状态时,关键部分是将其视为不可变的.如果你能保证,任何解决方案都可以正常工作.

这是我使用immutability-helper的解决方案:

jsFiddle:http://jsfiddle.net/eLmwf14a/

  var update = require('immutability-helper');

  handleCommentEdit: function(id, text) {
    var data = this.state.data;
    var commentIndex = data.findIndex(function(c) { 
        return c.id == id; 
    });

    var updatedComment = update(data[commentIndex], {text: {$set: text}}); 

    var newData = update(data, {
        $splice: [[commentIndex, 1, updatedComment]]
    });
    this.setState({data: newData});
  },
Run Code Online (Sandbox Code Playgroud)

以下有关状态数组的问题也可能有所帮助

  • 我最终使用map来更新数组.var newData = this.state.data.map(function(c){return c.id == id?React.addons.update(c,update):c;}); (5认同)

dai*_*no3 10

试图清理/解释更好地如何做到这一点以及发生了什么.

  • 首先,在状态数组中找到要替换的元素的索引.
  • 第二,update该指数的元素
  • 第三,setState使用新系列调用
import update from 'immutability-helper';

// this.state = { employees: [{id: 1, name: 'Obama'}, {id: 2, name: 'Trump'}] } 

updateEmployee(employee) {
    const index = this.state.employees.findIndex((emp) => emp.id === employee.id);
    const updatedEmployees = update(this.state.employees, {$splice: [[index, 1, employee]]});  // array.splice(start, deleteCount, item1)
    this.setState({employees: updatedEmployees});
}
Run Code Online (Sandbox Code Playgroud)

编辑:有一个更好的方法来做这个与第三方库

    const index = this.state.employees.findIndex(emp => emp.id === employee.id),
          employees = [...this.state.employees] // important to create a copy, otherwise you'll modify state outside of setState call
    employees[index] = employee;
    this.setState({employees});
Run Code Online (Sandbox Code Playgroud)


Uma*_*med 5

您可以通过多种方式执行此操作,我将向您展示我最常使用的方法。当我在React中使用数组时,通常会传递具有当前索引值的自定义属性,在下面的示例中,我传递了data-index属性,data-是html 5约定。

例如:

//handleChange method.
handleChange(e){
  const {name, value} = e,
        index = e.target.getAttribute('data-index'), //custom attribute value
        updatedObj = Object.assign({}, this.state.arr[i],{[name]: value});
      
  //update state value.
  this.setState({
    arr: [
      ...this.state.arr.slice(0, index),
      updatedObj,
      ...this.state.arr.slice(index + 1)
    ]
  })
  }
Run Code Online (Sandbox Code Playgroud)