NgRx Reducer中修改对象属性报对象不可扩展错误
问题根因
NgRx 全局 Store 默认开启严格不可变校验,所有存入 Store 的对象都会被冻结(内部通过Object.freeze实现),禁止直接修改原对象属性、禁止给原对象新增/删除属性。你在 reducer 中直接给传入的pokemon对象赋值isAdded属性,本质是直接修改 Store 中已冻结的原状态对象,因此抛出Cannot add property isAdded, object is not extensible错误。
你之前的操作存在两个明显问题:
- 直接修改 Store 中冻结的原对象:违反 NgRx 不可变更新原则,是报错的核心原因
- 误用
Object.preventExtensions():该API的作用是主动将对象设置为不可扩展状态,禁止后续给对象新增属性,不管放在赋值操作前还是后,都和修复目标完全相悖,无法解决报错
修复方案
严格遵循 NgRx 的不可变数据原则,所有状态修改都不能直接操作原对象引用,必须基于原对象创建新副本,在副本上修改属性后再返回新状态。
修正后的 Reducer 代码如下:
on(addToCart, (state, { pokemon }) => { // 基于原pokemon创建浅拷贝,在副本上修改属性 const updatedPokemon: PokemonModel = { ...pokemon, isAdded: true }; return { ...state, loading: false, error: false, pokemons: [ ...state.pokemons.filter((pk) => pk.name !== pokemon.name), updatedPokemon ], }; }),
额外注意事项
你从 PokeApi 获取的原始宝可梦数据默认不包含isAdded、quantity这两个自定义字段,需要在第一次把API返回数据存入 Store 时,就补全这两个字段的初始值(比如isAdded: false、quantity: 1),避免后续操作出现字段缺失问题。
内容的提问来源于stack exchange,提问作者jgcarrillo
相关产品推荐
相关产品推荐

