简体   繁体   English

在反应状态下替换数组中的对象

[英]Replace object in array on react state

This question might fall a little on the side of a "best practice" question, but please bear with me. 对于“最佳实践”问题,这个问题可能有点落空,但请耐心等待。

Here is a portion of my state: 这是我州的一部分:

this.state = {
  typeElements: {
    headers: [
        {
          name: "h1",
          size: 70,
          lineHeight: 1.25,
          kearning: 0,
          marginAfter: 0
        }, {
          name: "h2",
          size: 70,
          lineHeight: 1.25,
          kearning: 0,
          marginAfter: 0
        }, {
          name: "h3",
          size: 70,
          lineHeight: 1.25,
          kearning: 0,
          marginAfter: 0
        }...

What I need to do is REPLACE the object at a given index on the headers array. 我需要做的是在headers数组的给定索引处替换对象。

I don't know how to do that with the setState method as in this.setState(headers[1] = {obj}) - but that's obviously invalid. 我不知道如何使用this.setState(headers[1] = {obj})的setState方法this.setState(headers[1] = {obj}) - 但这显然是无效的。 My current method is creating a new array and clobbering the old one like this: 我当前的方法是创建一个新的数组并破坏旧的数组,如下所示:

_updateStyle(props) {
  let newState = Object.assign({}, this.state)
  newState.typeElements.headers[props.index] = props
  this.setState(newState)
};

For my small hacky project I guess it's OK but I feel like this is super heavy handed and would quickly lead to performance issues at any kind of scale. 对于我的小hacky项目,我想这没关系,但我觉得这是非常沉重的,很快就会导致任何规模的性能问题。

Updated: since this answer still gets upvotes, be aware that the previous answer below is outdated with modern JavaScript and React. 更新:因为这个答案仍然得到了回报,请注意以下的答案已经过时了现代JavaScript和React。 The "update" addon is now legacy and "immutability-helper" can be used instead. “更新”插件现在是遗留的,可以使用“immutability-helper”代替。

The React docs also mention why immutability is important so avoid mutating state. React文档还提到了为什么不变性很重要所以避免变异状态。 For immutable updates you can use Object.assign() or spread syntax which needs to be done for every level of nesting, like in this example the nested headers object and its array elements. 对于不可变更新,您可以使用Object.assign()扩展语法 ,这些语法需要针对每个嵌套级别进行,例如嵌套headers对象及其数组元素。 In this particular example we can use the array index as key so it's possible to also use the spread operator to make a shallow clone of the array and assign a new object as value at given index in the cloned array. 在这个特定的例子中,我们可以使用数组索引作为键,因此也可以使用spread运算符来生成数组的浅层克隆,并在克隆数组中的给定索引处将新对象指定为值。

_updateStyle (props) {
  const { typeElements } = this.state;
  const updatedHeaders = [...typeElements.headers];
  updatedHeaders[props.index] = props;
  this.setState({
    ...this.state,
    typeElements: {
      ...typeElements,
      headers: updatedHeaders
    }
  ));
}

Another solution which doesn't require the spread syntax and is needed if we are not using the array index to find the object we want to replace, is using array.map to create a new array and returning the new object instead of the old one at given index. 另一个不需要扩展语法的解决方案,如果我们不使用数组索引来找到我们想要替换的对象,则需要使用array.map创建一个新数组并返回新对象而不是旧对象在指定的指数。

  const updatedHeaders = typeElements.headers.map((obj, index) => {
    return index === props.index ? props : obj;
  });

Similar examples in the Redux docs also explain "immutable update patterns" . Redux文档中的类似示例也解释了“不可变更新模式”

React has some immutability helpers for this, which is explained in the docs: https://facebook.github.io/react/docs/update.html React为此提供了一些不变的帮助,这在文档中有解释: https//facebook.github.io/react/docs/update.html

In your case you could use the $splice command to remove one item and add the new one at given index, for example: 在您的情况下,您可以使用$ splice命令删除一个项目并在给定索引处添加新项目,例如:

 _updateStyle (props) { this.setState(update(this.state.typeElements, { $splice: [[props.index, 1, props]] } )); } 

use immutability-helper 使用immutability-helper

you can find nice examples there 你可以在那里找到很好的例子

Object.Assign uses shallow copy, not deep copy. Object.Assign使用浅拷贝,而不是深拷贝。

Please be aware that in your example Object.assign({}, this.state) copies only links to the nearest children of the state , ie to typeElements , but headers array is not copied. 请注意,在您的示例中, Object.assign({}, this.state)仅复制到该state最近的子级的链接,即typeElements ,但不复制headers数组。

There is a syntactic sugar ... in ES6 for Object.Assign, Babel has the special addon transform-object-rest-spread . 在ES6中有一个语法糖...对象.Assign,Babel有特殊的插件变换 - 对象 - 休息 - 传播

let newHeaders = { ...this.state.typeElements.headers};
newHeaders[index] = props.Something;

let newState = {...state, typeElements: { newHeaders }};

Offering a better explanation of how to accomplish this. 提供更好的解释如何实现这一目标。

  • First, find the index of the element you're replacing in the state array. 首先,在状态数组中找到要替换的元素的索引。
  • Second, update the element at that index 其次, update该索引处的元素
  • Third, call setState with the new collection 第三,使用新集合调用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});
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM