首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在setState中复制对象/数组的正确方法

在setState中复制对象/数组的正确方法
EN

Stack Overflow用户
提问于 2017-12-03 22:41:24
回答 7查看 45.7K关注 0票数 18

首先,我要:

代码语言:javascript
运行
复制
constructor() {
   super();
      this.state = {
         lists: ['Dogs','Cats'], 
         items: {Dogs: [{name: "Snoopy"}, {name: "Lola"}, {name: "Sprinkles"}], 
                 Cats: [{name: "Felidae"}, {name: "Garfiled"}, {name: "Cat in the Hat"}] }             
   };

}

然后我有了我的addItem函数:

代码语言:javascript
运行
复制
handleAddItem(s) {      

  var key = Object.keys(s)[0];
  var value = s[key];

  var allItems = {...this.state.items};

      allItems[key].push({name: value});    

      this.setState({items: allItems});
}

在其他地方,我将s定义为:

代码语言:javascript
运行
复制
var s={};
   s[this.props.idName] = this.refs.id.value;

这是可行的,但我想知道这是否是将元素添加到项目中的一个键中的正确方法。AllItems确实指向了this.state.items,我认为它应该是一个很深的副本,但我不知道如何做到这一点。

项目似乎是一个包含键/值对的对象,其中值是一个数组。对吗?我到哪里去学习如何操作这样的结构呢?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2017-12-03 22:58:36

我个人依赖于这种深层次的复制策略。JSON.parse(JSON.stringify(object))而不是spread操作符,因为它使我在处理嵌套对象或多维数组时陷入了奇怪的bug。

如果我是正确的,spread操作符不会进行深度复制,并且会导致嵌套对象的状态突变。

请通过代码来更好地理解两者之间正在发生的事情。假设这是使用spread运算符变异的状态变量。

代码语言:javascript
运行
复制
const obj = {Dogs: [{name: "Snoopy"}, {name: "Lola"}, {name: "Sprinkles"}], Cats: [{name: "Felidae"}, {name: "Garfiled"}, {name: "Cat in the Hat"}] };

const newObj = {...obj};
console.log("BEFORE SPREAD COPY MUTATION")

console.log("NEW OBJ: " + newObj.Dogs[0].name); //Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); //Snoopy

newObj.Dogs[0].name = "CLONED Snoopy";

console.log("AFTER SPREAD COPY MUTATION")

console.log("NEW OBJ: " + newObj.Dogs[0].name); // CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy

// Even after using the spread operator the changed on the cloned object are affected to the old object. This happens always in cases of nested objects.

// My personal reliable deep copy

console.log("*********DEEP COPY***********");

console.log("BEFORE DEEP COPY MUTATION")
deepCopyObj = JSON.parse(JSON.stringify(obj));


console.log("NEW OBJ: " + newObj.Dogs[0].name); //CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy
console.log("DEEP OBJ: " + deepCopyObj.Dogs[0].name); //CLONED Snoopy


deepCopyObj.Dogs[0].name = "DEEP CLONED Snoopy";

console.log("AFTER DEEP COPY MUTATION")
console.log("NEW OBJ: " + newObj.Dogs[0].name); // CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy
console.log("DEEP OBJ: " + deepCopyObj.Dogs[0].name); // DEEP CLONED Snoopy

现在,如果您想对对象进行深度复制,请将处理程序更改为

代码语言:javascript
运行
复制
handleAddItem(s) {      

  var key = Object.keys(s)[0];
  var value = s[key];

  var allItems = JSON.parse(JSON.stringify(this.state.items));

      allItems[key].push({name: value});    

      this.setState({items: allItems});
}
票数 38
EN

Stack Overflow用户

发布于 2018-11-10 00:19:07

我想添加更多关于克隆数组的信息。您可以调用切片,提供0作为第一个参数:

代码语言:javascript
运行
复制
const clone = myArray.slice(0);

上面的代码创建原始数组的克隆;请记住,如果数组中存在对象,则保留引用;也就是说,上面的代码不会对数组内容进行“深度”克隆。

票数 3
EN

Stack Overflow用户

发布于 2017-12-03 23:00:35

一个问题可能是var allItems = {...this.state.items};只会对this.state.items做一个浅克隆。因此,当您将数据推入这个数组时,它将在调用setState之前更改现有的数组。

您可以使用Immutable.js来解决这个问题。

代码语言:javascript
运行
复制
import { List, fromJS, Map } from 'immutable';

constructor() {
   super();
      this.state = {
       lists: List(['Dogs','Cats']), 
       items: fromJS({
        Dogs: [
          { name: "Snoopy" },
          ...
        ],
        Cats: [
          { name: "Felidae" },
          ...
        ]
      })
   };
}

然后添加函数如下:

代码语言:javascript
运行
复制
handleAddItem(s) {      
  var key = Object.keys(s)[0];
  var value = s[key];

  var allItems = this.state.items.set(key, Map({ name: value }));
  this.setState({ items: allItems });
}

只是一个想法!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47624142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档