NgRx Reducer中更新含嵌套接口的可选状态属性时的报错问题及解决方案咨询
解决NgRx Reducer中嵌套状态更新的类型错误问题
我来帮你搞定这个NgReducer里的赋值报错问题~
问题根源
你遇到的报错本质上是类型安全问题:state.current被定义为StockCardInterface | null,当它是null的时候,你直接用...state.current去展开一个null值,TypeScript会直接抛出类型错误,而且运行时也会出问题。另外从业务逻辑来说,如果current本身就是null,更新它的comments属性也没有意义。
符合NgRx最佳实践的解决方案
方案1:先判断current是否存在再更新
这是最直接的类型安全写法,在reducer里先检查state.current不为null,再执行更新操作:
on( fromStockCardAction.createStockCommentSuccess, (state, { comments }): StockCardState => { // 如果current是null,直接返回原状态(也可以根据业务需求做其他处理,比如抛出提示) if (!state.current) return state; return { ...state, load: { ...state.load, isLoading: false, isLoaded: true }, current: { ...state.current, comments: comments } }; } )
方案2:用三元运算符简化代码
如果想让代码更紧凑,可以用三元运算符处理null的情况:
on( fromStockCardAction.createStockCommentSuccess, (state, { comments }): StockCardState => ({ ...state, load: { ...state.load, isLoading: false, isLoaded: true }, current: state.current ? { ...state.current, comments: comments } : state.current }) )
方案3:使用NgRx Immer简化嵌套更新
如果你经常需要处理这类复杂的嵌套状态更新,推荐启用NgRx的Immer支持。Immer允许你用“可变”的写法编写reducer,它会自动帮你生成不可变的新状态,代码会简洁很多:
// 先导入createImmerReducer import { createImmerReducer, on } from '@ngrx/store'; const stockCardReducer = createImmerReducer( initialState, on(fromStockCardAction.createStockCommentSuccess, (state, { comments }) => { // 直接修改状态,Immer会自动处理不可变性 state.load.isLoading = false; state.load.isLoaded = true; // 同样要先判断current是否存在 if (state.current) { state.current.comments = comments; } }) );
额外的最佳实践提示
- 永远在reducer里处理null/undefined状态:Reducer是纯函数,不能依赖外部流程保证状态不为空,必须自己做类型安全检查。
- 保持状态不可变性:你已经通过展开运算符
...处理了嵌套状态的更新,这一点做得很对,继续保持。 - 从业务流程上规避无效操作:可以在触发
createStockComment动作前,先检查current是否已经加载(比如在组件或Effect里判断),避免不必要的reducer执行。
内容的提问来源于stack exchange,提问作者Iutkin Egor
相关产品推荐
相关产品推荐

