Javascript 在React中设置状态期间克隆对象/阵列的正确方法
我首先说:Javascript 在React中设置状态期间克隆对象/阵列的正确方法,javascript,reactjs,Javascript,Reactjs,我首先说: constructor() { super(); this.state = { lists: ['Dogs','Cats'], items: {Dogs: [{name: "Snoopy"}, {name: "Lola"}, {name: "Sprinkles"}], Cats: [{name: "Felidae"}, {name: "Garfiled"}, {name: "Cat in th
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确实指向了这个.state.items,我认为它应该是一个深度副本,但我不知道如何做到这一点
似乎items是一个对象,它保存键/值对,其中值是一个数组。对吗?我可以去哪里学习如何操作这样的结构?我个人依赖这种深度复制策略。
JSON.parse(JSON.stringify(object))
而不是spread
操作符,因为它让我在处理嵌套对象或多维数组时陷入了奇怪的错误
spread
运算符不会执行深度复制,如果我的判断正确,将导致React中嵌套的对象发生状态突变
请运行代码以更好地了解两者之间发生的情况。假设这是使用spread
运算符进行变异的状态变量
const obj={Dogs:[{name:“Snoopy”}、{name:“Lola”}、{name:“springs”})、Cats:[{{name:“Felidae”}、{name:“garfield”}、{name:“帽子里的猫”};
const newObj={…obj};
console.log(“扩散拷贝变异前”)
console.log(“newObj:+newObj.Dogs[0].name”)//史努比
console.log(“旧对象:+OBJ.Dogs[0].name”)//史努比
newObj.Dogs[0].name=“克隆史努比”;
console.log(“扩散拷贝变异后”)
console.log(“newObj:+newObj.Dogs[0].name);//克隆史努比
console.log(“旧对象:+OBJ.Dogs[0].name);//克隆史努比
//即使在使用“扩展”操作符后,克隆对象上的更改也会影响到旧对象。这通常发生在嵌套对象的情况下。
//我个人可靠的深拷贝
console.log(“**********深度拷贝*************”);
console.log(“深度复制变异前”)
deepCopyObj=JSON.parse(JSON.stringify(obj));
console.log(“newObj:+newObj.Dogs[0].name”)//克隆史努比
console.log(“旧对象:+OBJ.Dogs[0].name);//克隆史努比
log(“DEEP OBJ:+deepCopyObj.Dogs[0].name”)//克隆史努比
deepCopyObj.Dogs[0].name=“深度克隆史努比”;
console.log(“深度复制变异后”)
console.log(“newObj:+newObj.Dogs[0].name);//克隆史努比
console.log(“旧对象:+OBJ.Dogs[0].name);//克隆史努比
console.log(“DEEP OBJ:+deepCopyObj.Dogs[0].name);//深度克隆Snoopy
一个问题可能是var allItems={…this.state.items}
将仅对此.state.items
进行浅克隆。因此,当您将数据推入此数组时,它将在您调用setState
之前更改现有数组
你可以用它来解决这个问题
import { List, fromJS, Map } from 'immutable';
constructor() {
super();
this.state = {
lists: List(['Dogs','Cats']),
items: fromJS({
Dogs: [
{ name: "Snoopy" },
...
],
Cats: [
{ name: "Felidae" },
...
]
})
};
}
然后您的add函数将如下所示:
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 });
}
只是一个想法 我想添加更多关于克隆阵列的信息。您可以调用,将0作为第一个参数:
const clone = myArray.slice(0);
上面的代码创建了原始阵列的克隆;请记住,如果数组中存在对象,则会保留引用;i、 e.上面的代码没有对数组内容进行“深度”克隆。选择的答案是一个奇迹,是南都卡拉迪迪的巨大支柱,我在项目中更新的对象内部有嵌套数组的bug,我不理解“深度”或“嵌套”数组的概念,对象没有被复制到新对象 这是我对他的修复的看法,让它看起来更吸引我,效果也一样好 我利用
lodash
并找到了它们的.cloneDeep()
函数来满足我的更新状态需求
我了解到,绘制出防止任何bug的更新数组是处理此类问题的最佳方法,但我正在使用嵌套数组克隆整个对象,这些嵌套数组在状态中变异旧对象的数组
这是我的答案
const state = {
fields: {
"caNyDcSDVb": {
id: "caNyDcSDVb",
name: "test1",
type: "text",
options: ["A", "B", "C"]
}
},
};
const FieldCopy = (id) => {
const newCopiedField = _.cloneDeep(state.fields[id]);
newCopiedField.id = nanoid(10);
return {
...state,
fields: {
...state.fields,
newCopiedField[id]: newCopiedField
}
};
};
但我们似乎正在直接更改状态,因为allItems实际上指向this.state.items。这就是为什么您不直接执行
this.state={dogs:[],cats:[]}
。当我尝试你的map函数时,我得到构造函数map需要'new'这意味着什么?我从'immutable'中添加了{map}请注意,这可能会导致数据丢失。例如,日期似乎效率低下?