首先,我要:
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函数:
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定义为:
var s={};
s[this.props.idName] = this.refs.id.value;这是可行的,但我想知道这是否是将元素添加到项目中的一个键中的正确方法。AllItems确实指向了this.state.items,我认为它应该是一个很深的副本,但我不知道如何做到这一点。
项目似乎是一个包含键/值对的对象,其中值是一个数组。对吗?我到哪里去学习如何操作这样的结构呢?
发布于 2017-12-03 22:58:36
我个人依赖于这种深层次的复制策略。JSON.parse(JSON.stringify(object))而不是spread操作符,因为它使我在处理嵌套对象或多维数组时陷入了奇怪的bug。
如果我是正确的,spread操作符不会进行深度复制,并且会导致嵌套对象的状态突变。
请通过代码来更好地理解两者之间正在发生的事情。假设这是使用spread运算符变异的状态变量。
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
现在,如果您想对对象进行深度复制,请将处理程序更改为
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});
}发布于 2018-11-10 00:19:07
我想添加更多关于克隆数组的信息。您可以调用切片,提供0作为第一个参数:
const clone = myArray.slice(0);上面的代码创建原始数组的克隆;请记住,如果数组中存在对象,则保留引用;也就是说,上面的代码不会对数组内容进行“深度”克隆。
发布于 2017-12-03 23:00:35
一个问题可能是var allItems = {...this.state.items};只会对this.state.items做一个浅克隆。因此,当您将数据推入这个数组时,它将在调用setState之前更改现有的数组。
您可以使用Immutable.js来解决这个问题。
import { List, fromJS, Map } from 'immutable';
constructor() {
super();
this.state = {
lists: List(['Dogs','Cats']),
items: fromJS({
Dogs: [
{ name: "Snoopy" },
...
],
Cats: [
{ name: "Felidae" },
...
]
})
};
}然后添加函数如下:
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 });
}只是一个想法!
https://stackoverflow.com/questions/47624142
复制相似问题