NGRX - 如何通过reducer更新数组中对象中的字段?

Posted

技术标签:

【中文标题】NGRX - 如何通过reducer更新数组中对象中的字段?【英文标题】:NGRX - How to update a field in an object in an array by reducer? 【发布时间】:2020-03-26 05:24:51 【问题描述】:

如何通过 reducer 更新数组中的字段?我试过这个:

const customers = state.filteredCustomers;
for (const customer of customers) 
    for (const addr of customer.addresses) 
         addr.selected = false;
    


return 
    ...state,
    filteredCustomers: customers,
;

但是它会抛出一个错误:

 TypeError: Cannot assign to read only property 'selected' of object '[object Object]'

最好的方法是什么?

【问题讨论】:

【参考方案1】:

您可以使用 map 返回具有更新值的新客户数组。

return 
  ...state,
  filteredCustomers: customers.map(customer => 
    // Either use a second map or another loop
    for (const addr of customer.addresses) 
      addr.selected = false;
    
    return customer;
  )
;

【讨论】:

addr.selected = false; 又不行了!甚至用过地图。【参考方案2】:

错误似乎是一些不可变的引用发生了变异。我会尝试这样的事情。

    const customers = state.filteredCustomers;

    const updatedCustomers = customers.map( customer => (
...customer, addresses: customer.addresses.map( address => ( ...address, selected: false 
));

    return 
        ...state,
        filteredCustomers:  ...state.filteredCustomers, ...updatedCustomers  ,
    ;

【讨论】:

【参考方案3】:

您必须复制该州的每个级别。在这里,更新 x 层深度的嵌套状态可能会变得很尴尬。这就是为什么我会鼓励normalizing your state。

基本上,您必须遍历客户并复制属性,接下来您必须对地址执行相同操作并将 selected 设置为 false。

return 
    ...state,
    filteredCustomers: state.filteredCustomers.map(c => (
       ...c,
       addresses: c.adresses.map(a => (...a, selected: false)
    )
;

第二种选择是使用 immer,Clean NgRx reducers using Immer 有一个库可以为 NgRx 8 中的 createReducer 函数执行此操作 - https://github.com/timdeschryver/ngrx-etc/#mutableon。通过这种方法,您可以使用问题中发布的代码 sn-p。

【讨论】:

但我的状态是一个类实例的数组。这使它们成为没有任何方法的对象【参考方案4】:
import _ from 'lodash';

并在您的代码中使用

const tags: IAreaTag[] = _.cloneDeep(department.tags);

然后返回常量

所以在你的代码中

const customers = _.cloneDeep(state.filteredCustomers);

【讨论】:

以上是关于NGRX - 如何通过reducer更新数组中对象中的字段?的主要内容,如果未能解决你的问题,请参考以下文章

更新 ngrx/store 中的对象

如何从 ngrx 存储中获取数据并将其更新到 Observable 变量中?

在 @ngrx/store 4.0 中提供 root reducer

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

ngrx 中的 reducer 和不变性

Angular 6 ngrx,如何将新项目添加到状态对象的数组中?