在 ReactJS 中更新数组中对象的最佳方法是什么?
Whats the best way to update an object in an array in ReactJS?
如果您有一个数组作为状态的一部分,并且该数组包含对象,那么通过更改其中一个对象来更新状态的简单方法是什么?
示例,修改自 React 教程:
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});
}
}
更新状态的关键部分是将其视为不可变的。如果你能保证,任何解决方案都可以正常工作。
这是我使用 immutability-helper 的解决方案:
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});
},
以下有关状态数组的问题也可能有所帮助:
- Correct modification of state arrays in ReactJS
- what is the preferred way to mutate a React state?
你可以通过多种方式做到这一点,我将向你展示我最常使用的。当我在 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)
]
})
}
我非常喜欢使用 Object.assign 而不是不变性帮助程序。
handleCommentEdit: function(id, text) {
this.setState({
data: this.state.data.map(el => (el.id === id ? Object.assign({}, el, { text }) : el))
});
}
我只是认为这比 splice 简洁得多,并且不需要知道索引或显式处理未找到的情况。
如果你感觉全是 ES2018,你也可以用 spread 代替 Object.assign
this.setState({
data: this.state.data.map(el => (el.id === id ? {...el, text} : el))
});
尝试清理/更好地解释如何执行此操作以及发生了什么。
- 首先,在状态数组中找到您要替换的元素的索引。
- 其次,
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});
}
编辑:有更好的方法来做到这一点w/o第 3 方库
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});
如果您有一个数组作为状态的一部分,并且该数组包含对象,那么通过更改其中一个对象来更新状态的简单方法是什么?
示例,修改自 React 教程:
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});
}
}
更新状态的关键部分是将其视为不可变的。如果你能保证,任何解决方案都可以正常工作。
这是我使用 immutability-helper 的解决方案:
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});
},
以下有关状态数组的问题也可能有所帮助:
- Correct modification of state arrays in ReactJS
- what is the preferred way to mutate a React state?
你可以通过多种方式做到这一点,我将向你展示我最常使用的。当我在 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)
]
})
}
我非常喜欢使用 Object.assign 而不是不变性帮助程序。
handleCommentEdit: function(id, text) {
this.setState({
data: this.state.data.map(el => (el.id === id ? Object.assign({}, el, { text }) : el))
});
}
我只是认为这比 splice 简洁得多,并且不需要知道索引或显式处理未找到的情况。
如果你感觉全是 ES2018,你也可以用 spread 代替 Object.assign
this.setState({
data: this.state.data.map(el => (el.id === id ? {...el, text} : el))
});
尝试清理/更好地解释如何执行此操作以及发生了什么。
- 首先,在状态数组中找到您要替换的元素的索引。
- 其次,
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});
}
编辑:有更好的方法来做到这一点w/o第 3 方库
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});