我有一个连接到Redux存储的组件,该组件接收一个prop并将其传递给子组件。

在子组件中,我以这种方式在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数组中的最后一个对象; 或者,如果不存在componentslastItem添加到对象dailyData 最后,只有一系列concat()才能获得没有嵌套对象的单个数组。

该代码有效,但是这里的一个奇怪的事实是,当我在this.props.internalData上调用map()函数时,商店internalData的prop internalData也被编辑了。

您能帮助您理解为什么会发生吗?

谢谢

#1楼 票数:1 已采纳

Javascript通过引用传递对象。 这意味着,如果克隆对象(所谓的“浅克隆”),则实际上会更改主对象引用,但嵌套属性保持不变。 当您map对象数组或调用Object.assign({}, /.../)时,就会发生这种情况。

因此,当您像a.dayData.lastItem = true那样更改a.dayData.lastItem = true ,实际上是在更改原始属性。 Map将返回克隆的对象,但是此特定分配更改了原始属性的引用值。

为了解决它,您有多种方法:

  1. 克隆整个对象和每个属性(深层克隆)
  2. 不要更改属性,而只是传递一个新值(在每次map迭代中构造一个新对象);

另外,摆脱这些多个[].concat.apply ,可能不需要它们:)

解决方案:

1.您可以尝试使用_.cloneDeephttps : _.cloneDeep

// Inside your map
const clonedA = _.cloneDeep(a);

if(clonedA.hasOwnProperty("components")){ 
   clonedA.components[clonedA.components.length-1].lastItem = true
} else {
   clonedA.dayData.lastItem = true
} 

return clonedA;

但是要警告! 对于大型物体,它可能非常慢(它必须遍历所有结构)。

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 (不要忘记使用{}作为第一个参数调用Object.assign !)。对性能有重大影响。

对于您的情况,我建议遵循我的第二条建议-只需在数据结构的每个级别上创建新对象。 我还建议将这些操作转移给助手,因为您会看到代码变得相当复杂且有些丑陋。

  ask by marco translate from so

未解决问题?本站智能推荐:

2回复

使用map()遍历React中的嵌套Prop

我目前正在使用react渲染一个名为area的道具,如下所示: 更新2- 这工作 : 输出: 结合地图,这个工程 输出: 但是当我包含{this.renderCountries()} ,它什么也不会输出,这就是为什么我无法获得建议的原因。 在Firefox上,两个大陆
1回复

在React中通过map方法传递prop

我需要映射一个数组来输出一堆组件。 我遇到的困难是将函数作为道具传递 - 它看起来像这样: ...但我无法从地图访问 myFunction。 我知道我可以使用上下文,但是我如何使用道具来实现这一点?
2回复

prop函数中的React-prop函数

我正试图在我的一个组件的另一个道具中执行道具。 基本上我必须等待一些数据从API返回,然后我想执行下一个道具。 这是我的组件2道具代码: 不确定这是否是React开始时的正确方法? 如果是这样,那么不确定为什么道具没有开火......
2回复

React-Redux:如何使用异步调用中的数据填充加载时的组件的prop?

我有这个自动完成组件,它需要一个术语数组作为dataSource属性。 我要输入的数据驻留在公共API中,我已经按照此处的教程操作,以获取以下代码。 但是本教程(以及其他许多教程)介绍了如何将这些动作绑定到事件,而我想用页面加载数据填充此道具。 我将如何去做? actions.js
2回复

无法读取通过Redux传递的React功能组件中的prop

这是示例反应功能组件 当我执行console.log(props)它会显示以下内容 如果您看到存在用户对象。 我使用以下道具从道具中检索该用户 我看到了用户数据 最后,当我想获取用户的名称时console.log(user.name) 它说 出了什么问题?
1回复

在React-NativeFormikonBlur()函数中调用prop和function

目前,我试图同时在onBlur TextInput函数中调用函数和formikProps。 我要实现的目标: 当我离开Textinput时,我将isFocused的状态更改为true,因为我希望此时样式更改。 同样,我的Textinput应该触发handleBlur()。 但事实并非如此。
1回复

在调用高阶组件时,在React中访问类外的prop

我试图使用高阶组件(HOC)模式重用一些连接到状态的代码并使用Redux Form formValueSelector方法。 formValueSelector需要一个引用表单名称的sting。 我想动态设置它,并且只要我需要项目的值就可以使用这个HOC。 我使用项目值进行计算。 在
3回复

在Redux中构建商店

有没有一种方法来构造const reducer = (state = initialState, action) ,使该方法不会因一堆开关案例而肿? 我的想法是将相关动作放入数组中,并在处理动作时使用Array.prototype.includes()检查它们。 然后,我将提取与新方法中