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

如何在NgRx Reducer中向State嵌套对象的数组添加元素

NgRx Reducer中向嵌套Deck对象添加Card的解决方案

问题核心

NgRx Reducer必须遵循状态不可变原则,不能直接修改原State对象。直接调用currentDeck.addCard(card)会修改State中的原始对象,触发"can't define array index property past the end of an array with non-writable length"错误,必须通过创建副本的方式实现状态更新。

解决方案(无需安装Immer)

提供两种符合不可变原则的实现方式:

方式一:基于Deck类方法创建副本

先复制当前currentDeck实例,在副本上调用addCard方法后替换原对象:

on(addCardToCurrentDeckActions.addCardCurrentDeckSuccess, (state, { card }) => {
  // 处理currentDeck未初始化的边界情况
  if (!state.currentDeck) return state;

  // 创建Deck实例的完整副本
  const updatedDeck = new Deck();
  updatedDeck.deckId = state.currentDeck.deckId;
  updatedDeck.name = state.currentDeck.name;
  // 复制原cards数组,避免直接引用原数组
  updatedDeck.cards = [...state.currentDeck.cards];
  
  // 在副本上执行添加操作
  updatedDeck.addCard(card);

  return {
    ...state,
    currentDeck: updatedDeck
  };
})

方式二:手动构造新Deck对象(更简洁)

利用对象扩展语法直接创建新Deck对象,同时更新cards数组,无需依赖Deck类的方法:

on(addCardToCurrentDeckActions.addCardCurrentDeckSuccess, (state, { card }) => {
  if (!state.currentDeck) return state;

  return {
    ...state,
    currentDeck: {
      ...state.currentDeck,
      // 复制原cards数组并追加新Card
      cards: [...state.currentDeck.cards, card]
    }
  };
})

关键说明

  • 两种方式均未修改原State中的任何对象/数组,严格遵守NgRx不可变规则
  • 必须先判断currentDeck是否存在,避免undefined引发的运行时错误
  • 方式二更简洁高效,无需手动复制Deck的其他属性,直接通过扩展语法生成新对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:40:28