Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在react/redux中,对存储道具调用map()可编辑存储本身中的道具_Javascript_Reactjs - Fatal编程技术网

Javascript 在react/redux中,对存储道具调用map()可编辑存储本身中的道具

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

我有一个连接到Redux存储的组件,它接收一个道具并将其传递给子组件

在子组件中,我以这种方式在
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()
函数时,存储中的prop
internalData
也会被编辑

你能帮助理解为什么会这样吗


谢谢,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);