Javascript 在react/redux中,对存储道具调用map()可编辑存储本身中的道具
我有一个连接到Redux存储的组件,它接收一个道具并将其传递给子组件 在子组件中,我以这种方式在Javascript 在react/redux中,对存储道具调用map()可编辑存储本身中的道具,javascript,reactjs,Javascript,Reactjs,我有一个连接到Redux存储的组件,它接收一个道具并将其传递给子组件 在子组件中,我以这种方式在render()方法中详细阐述了这个道具 let dataForFlatList = [].concat.apply([], [].concat.apply([], this.props.internalData.map( a => { if(a.hasOwnProperty("components")){ a.components[a.components.length-1
render()
方法中详细阐述了这个道具
let dataForFlatList = [].concat.apply([], [].concat.apply([], this.props.internalData.map( a => {
if(a.hasOwnProperty("components")){
a.components[a.components.length-1].lastItem = true
} else {
a.dayData.lastItem = true
}
return Object.values(a)
})));
为清楚起见,Redux商店中的此道具具有以下结构:
[
{
dailyData: {
date: .....
steps: .....
},
components: [ {...}, {...}, {...}, {...}, {...} ...]
},
{
dailyData: {
date: .....
steps: .....
},
components: [ {...}, {...}, {...}, {...}, {...} ...]
},
{
dailyData: {
date: .....
steps: .....
}
}
:::
]
因此,我要做的是将属性lastItem
添加到components
数组中的最后一个对象;或者,如果组件
不存在,则将lastItem
添加到对象dailyData
。
最后,这一系列的concat()
只是获得一个没有嵌套对象的数组所必需的
这段代码有效,但奇怪的是,当我调用This.props.internalData
上的map()
函数时,存储中的propinternalData
也会被编辑
你能帮助理解为什么会这样吗
谢谢,Javascript通过引用传递对象。这意味着,如果克隆对象(称为“浅克隆”),实际上会更改主对象引用,但嵌套属性保持不变。这正是当您映射对象数组或调用对象时发生的情况 因此,当您更改类似于
a.dayData.lastItem=true的内容时,实际上会改变原始属性。Map将返回克隆对象,但此特定指定会更改原始属性的引用的值
为了解决这个问题,您有多种方法:
克隆整个对象和每个属性(深度克隆)
不改变属性,只传递一个新值(在每次映射迭代中构造新对象)李>
另外,要去掉这些多个[].concat.apply
,它们可能是不需要的:)
解决方案:
1。您可以尝试使用\uu.cloneDeep
::
不过要小心!对于大型对象,它可能非常慢(它必须遍历所有结构)
2。您可以尝试这样传递新值:
if(a.hasOwnProperty("components")){
// We use empty slice to clone the array
const clonedComponents = components.slice();
const lastArrayElement = clonedComponents[clonedComponents.length-1];
clonedComponents[clonedComponents.length - 1] = Object.assign({}, lastArrayElement, { lastItem: true });
return Object.assign({}, a, { components: clonedComponents});
} else {
// Note empty object as the first param - we also return completely new value
return Object.assign({}, a, { dayData: { lastItem: true } });
}
return Object.values(a);
在映射对象时,如果我知道对象的状态(不要忘记调用对象。使用{}
作为第一个参数分配),我仍然喜欢使用.cloneDeep
或.merge
)
在您的情况下,我建议遵循我的第二个建议——在数据结构的每一层上创建新对象。我还建议将这些操作移动到助手,因为您可以看到代码变得非常复杂,而且有点难看。不,map
不会改变任何东西。您的.lastItem=true
赋值确实如此。@Bergi好吧,但即使我在一个新数组中复制我的道具,比如让d=[…this.props.internalData]
并对其执行map()操作,它也会编辑存储中的道具…是的,因为数组并不重要。您正在更改component对象的属性,这就是发生变异的地方。@Bergi您能给我建议其他方法吗?@marco您正在通过为数组中的项赋值来修改该项的属性。
if(a.hasOwnProperty("components")){
// We use empty slice to clone the array
const clonedComponents = components.slice();
const lastArrayElement = clonedComponents[clonedComponents.length-1];
clonedComponents[clonedComponents.length - 1] = Object.assign({}, lastArrayElement, { lastItem: true });
return Object.assign({}, a, { components: clonedComponents});
} else {
// Note empty object as the first param - we also return completely new value
return Object.assign({}, a, { dayData: { lastItem: true } });
}
return Object.values(a);