Ngrx select仅首次触发返回undefined 每次dispatch后未正常触发问题
NgRx select未按预期触发问题解决方案
- 原因1:状态切片未正确注册
你调用this.store.select(state => state.name)是从NgRx根状态中读取name切片,必须在根模块导入StoreModule时将对应reducer绑定到name键,否则根状态中不存在该属性,且dispatch的action没有对应reducer处理,状态不会发生变更:
// app.module.ts 正确示例 import { NgModule } from '@angular/core'; import { StoreModule } from '@ngrx/store'; import { nameReducer } from './name.reducer'; @NgModule({ imports: [ StoreModule.forRoot({ // 此处键名必须和select时取的键名完全一致 name: nameReducer }) ] }) export class AppModule {}
如果是用特性模块注册状态,需要保证select的路径和特性名匹配,比如注册StoreModule.forFeature('user', {name: nameReducer}),则select写法应为this.store.select(state => state.user.name)。
- 原因2:reducer未遵循不可变原则
NgRx依赖状态对象的引用变化判断是否更新,如果你在reducer中直接修改原状态对象而不是返回全新对象,会被判定为无状态变化,不会触发select更新:
// 错误写法 function badReducer(state, action) { if (setName.match(action)) { state.name = action.name; // 直接修改原对象,引用不变 return state; } return state; } // 正确写法 function goodReducer(state, action) { if (setName.match(action)) { // 返回全新对象,引用变化触发更新 return { ...state, name: action.name }; } return state; }
同时要注意给reducer设置正确的初始状态,避免首次select返回undefined:
const initialState = { name: '' }; function goodReducer(state = initialState, action) { // 逻辑同上 }
- 原因3:Observable未被订阅
RxJS的Observable只有被订阅时才会执行流内逻辑,如果你只是声明了name$但没有在模板中使用| async管道,也没有手动调用subscribe方法,tap(console.log)只会在初始化时执行一次,后续状态变化不会触发日志打印。
内容的提问来源于stack exchange,提问作者dorty
相关产品推荐
相关产品推荐

