You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NgRx reducer更新roles数组name属性报错的正确实现方案

问题描述

我的State定义如下:

roles =[ {
  roleId:"8e8be141-130d-4e5c-82d2-0a642d4b73e1",
  name:"HR",
  description:"HR of the Company",
  isModerator:"N"
},
{
  roleId:"8e8be141-130d-4e5c-82d2-0a642d4b73e1",
  name:"MR",
  description:"MR of the Company",
  isModerator:"Y"
}]

我编写的reducer代码如下:

on(updateRoleItem, (s, { roleId, item }) => {
  let modifiedState = [...s];
  modifiedState.map((data) => {
    if (data.roleId === roleId) {
      data.name = item;
    }
  })
  return modifiedState;
})
);

当前运行触发报错,报错截图如下:
报错截图

我需要实现更新roles角色数组中指定roleId对应角色的name属性的功能,当前实现逻辑为匹配roleId找到目标对象后修改其name属性,但运行时出现报错,希望得到符合NgRx规范的正确实现方式。


问题原因

代码触发报错的核心是违反NgRx不可变状态更新规则,同时存在语法和逻辑问题:

  1. [...s]仅对数组本身做浅拷贝,数组内的角色对象仍指向原状态的内存引用,直接给data.name赋值属于直接篡改原状态对象,NgRx检测到非法状态变更就会抛出错误。
  2. Array.map的设计用途是遍历生成新数组,当前代码没有使用map的返回值,反而在遍历回调里修改原对象,属于API误用。
  3. 初始状态中两个角色的roleId完全重复,实际业务必须保证roleId全局唯一,否则匹配逻辑会同时命中多个条目,导致更新结果不符合预期。
  4. 现有reducer代码末尾多了一个多余的闭合括号,存在语法错误,编写时需要注意语法校验。

符合NgRx规范的正确实现

on(updateRoleItem, (state, { roleId, item }) => {
  return state.map(role => {
    // 非目标角色直接返回原引用,不需要额外拷贝,避免不必要的组件重渲染
    if (role.roleId !== roleId) {
      return role;
    }
    // 匹配到目标角色时,展开原对象生成新对象,覆盖要更新的name属性
    return {
      ...role,
      name: item
    };
  });
})

该实现全程不会修改任何原有状态的属性,所有更新都通过生成新引用的方式完成,完全符合NgRx的状态更新要求,同时代码更简洁,运行性能更优。

内容的提问来源于stack exchange,提问作者Benezir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:30:43