NGRX中Reducer未触发?如何正确将Reducer接入Store?
问题描述
我在服务中dispatch addHero动作时,能看到每个Hero对应的"obtaining"和"dispatched"日志,但Reducer似乎未被调用。该服务的run方法在ngOnInit钩子中触发。
更新:我已将appReducer包装为一个函数,用于记录每次Reducer调用并调用实际Reducer,但仍未看到相关日志,推测可能在Reducer接入Store的环节存在疏漏。我在module.ts的imports中尝试了如下代码:
StoreModule.forRoot(appReducer)
相关代码
服务代码
export class GetTheActualListOfHeroesService { store: Store<AppStore>; run(): void { console.log("GetTheActualListOfHeroesService") obtainHeroesService().forEach(hero => { console.log("obtaining", hero) this.store.dispatch(addHero(hero)) console.log("dispatched") } ) }; constructor(appStore: Store<AppStore>) { this.store = appStore; } }
Reducer代码(未看到"addHero"日志)
export const initialState: AppStore = { heroes: [], filterString: "", selectedHero: undefined } export const appReducer = createReducer( initialState, on(addHero, (state: AppStore, hero) => { console.log("addHero", hero) state.heroes.push(hero); console.log(state) return state; }), );
动作定义
export const addHero = createAction('add Hero', props<Hero>());
模块定义
@NgModule({ declarations: [ HeroesComponent, HeroeditorComponent, HeroitemComponent, HeroListComponent, HeroFilterComponent ], imports: [ BrowserModule, AppRoutingModule, FormsModule, StoreModule.forRoot(appReducer) ], providers: [ SelectedHeroRepository, HeroFilterRepository, GetTheActualListOfHeroesService, IsThisHeroSelectedForEditingService, SelectHeroForEditingService, InitializeStatesService, SelectHeroesWithMatchingNamesService, ], bootstrap: [HeroesComponent] }) export class Angulartest { }
请问我忽略了什么明显问题?
问题排查与解决
1. StoreModule.forRoot参数格式错误
NgRx的StoreModule.forRoot()要求传入键值对对象(state分片名称对应reducer),而非直接传入reducer函数。你当前的写法不符合规范,修改模块中的imports:
StoreModule.forRoot({ app: appReducer })
这里的app是state的分片标识,后续获取state时需要对应这个名称,比如store.select(state => state.app.heroes)。
2. Reducer直接修改原state对象
NgRx要求Reducer是纯函数,绝对不能直接修改原state,必须返回全新的state对象。你用state.heroes.push(hero)直接修改原数组,会导致NgRx无法检测到state变化,同时违反不可变数据原则。修改Reducer代码:
export const appReducer = createReducer( initialState, on(addHero, (state: AppStore, hero) => { console.log("addHero", hero) // 扩展运算符创建新数组,返回全新state对象 return { ...state, heroes: [...state.heroes, hero] }; }), );
3. 确认obtainHeroesService的返回值类型
如果obtainHeroesService()返回的是Observable,不能直接用forEach遍历,需要改用subscribe:
obtainHeroesService().subscribe(heroes => { heroes.forEach(hero => { console.log("obtaining", hero) this.store.dispatch(addHero(hero)) console.log("dispatched") }) })
4. 验证组件中服务的调用逻辑
确保组件的ngOnInit中正确调用了服务的run方法,且服务已被正确注入:
@Component({...}) export class HeroesComponent implements OnInit { constructor(private heroService: GetTheActualListOfHeroesService) {} ngOnInit(): void { this.heroService.run(); } }
内容的提问来源于stack exchange,提问作者Árpád Magosányi
相关产品推荐
相关产品推荐

