如何通过NgRx Reducer更新布尔类型状态属性值
NgRx Reducer 状态更新问题修复方案
你的代码存在4个核心问题,会导致状态无法正常更新:
- Action payload设计冗余:开关导航是固定修改
isNavOpen为true/false的操作,不需要传入整个GlobalModel作为参数,多余的传参反而容易引发状态覆盖错误。 - 初始状态不符合类型定义:你将
entities初始值设为null,状态初始化时navigation字段不存在,首次更新极易触发空值报错。 - Reducer更新逻辑错误:直接用传入的payload整体替换
entities,没有做逐层的不可变对象拷贝,也没有匹配到对应action时的默认返回分支,未命中的action会直接把状态置为undefined。 - 未确认reducer注册状态:写完reducer如果没有在NgRx Store中注册,状态不会被框架托管,自然无法正常更新。
修正后的Action代码(global.actions.ts)
去掉不需要的payload定义,动作本身就代表固定的状态变更意图:
import { Action } from "@ngrx/store"; export enum Types { NAV_OPEN = '[Global] NAV: open', NAV_CLOSE = '[Global] NAV: close', } export class NavOpen implements Action { readonly type = Types.NAV_OPEN; } export class NavClose implements Action { readonly type = Types.NAV_CLOSE; } export type All = NavOpen | NavClose;
修正后的Reducer代码
补全合法的初始状态,逐层做不可变更新,添加默认返回分支:
import { GlobalModel } from "./global.models"; import * as fromAction from './global.actions'; export interface GlobalState { entities: GlobalModel; } const initialState: GlobalState = { entities: { navigation: { isNavOpen: false } }, } export function reducer ( state = initialState, action: fromAction.All ) : GlobalState { switch(action.type) { case fromAction.Types.NAV_OPEN: { return { ...state, entities: { ...state.entities, navigation: { ...state.entities.navigation, isNavOpen: true } } } } case fromAction.Types.NAV_CLOSE: { return { ...state, entities: { ...state.entities, navigation: { ...state.entities.navigation, isNavOpen: false } } } } default: return state } }
检查Store注册配置
确保你已经在对应模块中注册了该reducer:
- 根模块中使用
StoreModule.forRoot({ global: reducer })导入注册 - 如果是特性模块的状态,使用
StoreModule.forFeature('global', reducer)注册
组件中调用示例:
import { Store } from '@ngrx/store'; import * as GlobalActions from './global.actions'; import { GlobalState } from './global.reducer'; constructor(private store: Store<{ global: GlobalState }>) {} // 触发打开导航 openNav() { this.store.dispatch(new GlobalActions.NavOpen()); } // 触发关闭导航 closeNav() { this.store.dispatch(new GlobalActions.NavClose()); } // 订阅导航状态 isNavOpen$ = this.store.select(state => state.global.entities.navigation.isNavOpen);
如果你使用NgRx 8+版本,更推荐官方提供的
createAction、createReducer函数式写法,能减少大量手动拷贝对象的样板代码,降低不可变更新的出错概率。
内容的提问来源于stack exchange,提问作者orphen92300
相关产品推荐
相关产品推荐

