ngrx 更新数组内的对象

Posted

技术标签:

【中文标题】ngrx 更新数组内的对象【英文标题】:ngrx update object inside array 【发布时间】:2020-08-17 05:59:15 【问题描述】:

我有一个带有对象数组的 ngrx 商店。我正在寻找的是,使用数组索引更新(修改)数组内的对象。 我的 ngrx 数据看起来像,

    policies: 
        beneficiaries: 
            beneficiaries: [
                    name: 'pqr'
                    age: 56
                ,
                
                    name: 'xyz'
                    age: 76
                
            ]
        
    

我必须根据数组索引更新受益人姓名。 于是我实现了如下reducer函数

    on(policiesActions.updateBeneficiaryPercentage, (state, action) => 
        return 
          ...state,
          beneficiaries: 
            ...state.beneficiaries,
            beneficiaries: 
              ...state.beneficiaries.beneficiaries,
              [action.index]: 
                ...state.beneficiaries.beneficiaries[action.index],
                name: action.value
              
            
          
        ;
      )

上述代码的问题在于 运行此代码后,我的商店结构将更改为

policies: 
    beneficiaries: 
        beneficiaries: 
            0: 
                name: 'pqr'
                age: 1000
            ,
            1: 
                name: 'xyz'
                age: 76
            
        
    

请帮助我修复代码,以便我可以在不更改存储结构的情况下更新值。

【问题讨论】:

【参考方案1】:

当更新数组中的对象时,我会重新创建一个包含所有排除对象的数组并附加最后一个需要更新值的对象。

const policies = 
  beneficiaries: 
    beneficiaries: [
        name: 'pqr',
        age: 56
      ,
      
        name: 'xyz',
        age: 76
      
    ]
  


const updateObject = (state, action) => 

  if(!state.beneficiaries.beneficiaries[action.index]) 
    return state;
  

  return 
    ...state,
    beneficiaries: 
      ...state.beneficiaries,
      beneficiaries: [
        ...state.beneficiaries.beneficiaries.slice(0, action.index),
        
          ...state.beneficiaries.beneficiaries[action.index],
          name: action.value
        ,
        ...state.beneficiaries.beneficiaries.slice(action.index + 1)
      ]
    
  ;


console.log(updateObject(policies, index: 1, value: 'test'))

--编辑

添加了 sn-p 并更改了逻辑,因此它不会更改列表顺序。

【讨论】:

这个正在工作...但是数组元素的顺序正在改变...即更新的元素将成为数组中的最后一个元素... 更新了答案。是的,当新状态更改列表顺序时,这根本没有意义。【参考方案2】:

使用Array.map 方法:

arr.map((value, index) => index === action.index ? ...value, name: action.value : value) 

或者只使用ngrx-etc,它可以让你以一种可变的方式改变你的状态,同时保持不可变

mutableOn(onAction, (state, action) => 
  state.arr[action.index].name = action.name
  return state
)

【讨论】:

ngrx-etc 是一个很棒的库,在某些情况下让开发人员免于编写繁琐的代码。当不应更改数组中的项目顺序时,这特别有用。谢谢。 请注意,ngrx-etc 已被 ngrx-immer (github.com/timdeschryver/ngrx-immer) 取代【参考方案3】:

您可以使用 immer.js 生成新状态,而无需触及之前的状态。无需推出自己的解决方案,而且通过手动克隆前一个对象来重新创建对象容易出错

import produce from "immer"

on(policiesActions.updateBeneficiaryPercentage, (state, action) => 
  return produce(state, draftState => 
    draftState.policies.beneficiaries.beneficiaries[action.index].name = action.value
  )
)

如果你想以实用的方式做到这一点,你可以试试镜头example using ramda

【讨论】:

【参考方案4】:

这是一种简单的方法,无需深入了解状态对象。

on(ProductActions.updateProductSuccess, (state, action): ProductState => 

  // define a constant and map over the existing state, inserting your new item,
  // then assign your new object as the new state.

  const updatedProducts = state.products.map(
  product => action.product.id === product.id ? action.product : product);
  return 
    ...state,
    products: updatedProducts
  
   ;
),

这假设您在成功操作中传递了一个完整的产品对象。

【讨论】:

以上是关于ngrx 更新数组内的对象的主要内容,如果未能解决你的问题,请参考以下文章

更新 ngrx/store 中的对象

如果 id 匹配,角度 ngrx 存储更新数组项

如何通过 Angular 中的 NGRX 减速器使用数组更新状态?

更新对象内的数组中的对象

如何更新猫鼬模式中另一个数组内的数组内的对象?

如何更新firestore中数组内的对象? [复制]