繁体   English   中英

@ngrx/store 组合功能模块中的多个减速器

[英]@ngrx/store combine multiple reducers from feature module

我目前正在开发一个简单的测试应用程序,以了解有关@ngrx/store 的更多信息。 我有一个名为 TrainingModule 的模块,它应该存储一些练习和更多信息。 该代码有效,但我尝试在这里改进。 我目前拥有的是我的功能模块,如下所示:

@NgModule({
  imports: [
    CommonModule,
    TrainingRoutingModule,
    StoreModule.forFeature('exercises', exerciseReducer)
  ],
  declarations: [
    TrainingDashboardComponent,
    TrainingCoreComponent,
    TrainingNavComponent,
    TrainingPlanComponent,
    ExerciseOverviewComponent,
    ExerciseListComponent]
})
export class TrainingModule {
}

和我的减速器看起来像这样:

export interface ExerciseState {
  exercises: IExercise[];
}

export interface State extends fromRoot.State {
  'exercises': ExerciseState;
}

export const initialState: ExerciseState = {
  exercises: [
    {id: 1, name: 'Exc 1'},
    {id: 2, name: 'Exc 2'}
  ]
};

export function exerciseReducer(state: ExerciseState = initialState, action: any): ExerciseState {
  switch (action.type) {
    default:
      return state;
  }
}

export const getExerciseState = createFeatureSelector<ExerciseState>('exercises');
export const getExercises = createSelector(getExerciseState, state => state.exercises);

到目前为止,一切都很好。 在我的模板中,我从商店中选择我的练习

exercise$: Observable<IExercise[]>;

  constructor(private store: Store<State>) { }

  ngOnInit() {
    this.exercise$ = this.store.select(getExercises);
  }

所以我现在想做的是结合我的减速器,这样我就不必像这样添加每个减速器

StoreModule.forFeature('exercises', exerciseReducer);
StoreModule.forFeature('sample', sampleReducer);
StoreModule.forFeature('sample1', sampleReducer1);

在我的所有模块中。 我试图收集所有减速器

export const trainingReducers = {
  'exercise': exerciseReducer
};

StoreModule.forFeature('training', trainingReducers)

但这给了我一个无法读取控制台中未定义错误消息的属性“练习”。 也许有人可以帮助我理解,我如何从功能模块中收集所有减速器并为此创建正确的选择器。

我可以给你举个例子,我是怎么做到的。 我使用 index.ts 来捆绑模块中的所有其他减速器,如下所示:

模块/减速器/index.ts

import * as fromRoot from '../../../reducers';
import * as fromSearch from './search';
import * as fromUserDetail from './user-detail';
import * as fromDetailBase from './base';


export interface UserModuleState {
  search: fromSearch.State;  
  detail: fromUserDetail.State;
  detailBase: fromDetailBase.State;
}

export interface State extends fromRoot.State {
    userModule: UserModuleState;    
}

export const reducers = {    
    search: fromSearch.reducer,
    detail: fromUserDetail.reducer,
    detailBase : fromDetailBase.reducer
};

export const selectUserModuleState = createFeatureSelector<UserModuleState>('userModule');


export const selectSearchState = createSelector(
    selectUserModuleState, (state: UserModuleState) => state.search
);
export const getSearchLoading = createSelector(selectSearchState, fromSearch.getLoading);
export const getSearchEntities = createSelector(selectSearchState, fromSearch.getEntities);

模块/用户.module.ts

import { reducers } from './reducers';
@NgModule({
    imports: [
        ...
        StoreModule.forFeature('userModule', reducers)
    ],
     ...
})
export default class UserModule { }

您的设置几乎是正确的。

createFeatureSelector函数中,您在商店的根目录中声明了一个功能键,在示例中为 'exercises'。 因此,您将选择store.exercises.exercises.id例如,功能选择器只是store.exercises的快捷方式。

但是,在StoreModule.forFeature('training', trainingReducers)调用中,您将 'training' 定义为功能模块的根键。

正确的设置可能如下所示:

export const featureReducersMap = {
  exercise: exerciseReducer,
  anyOtherKey: anyOtherReducer
};
StoreModule.forFeature('myFeatureModule', featureReducersMap);
export interface FeatureState{
  exercise: string;
  anyOtherKey: number;
}

然后编写选择器,如:

export const featureSelector = createFeatureSelector<FeatureState>('myFeatureModule');

export const exerciseSelector = createSelector(
  featureSelector,
  (state: FeatureState) => state.exercise
);

建议将特征键存储在变量中,而不是对其进行硬编码。

使用新功能createFeature您可以更轻松地完成它。

  1. 向 AppState 接口添加功能
export interface AppState {
  yourFeature: FeatureInterface
}
  1. 在模块内创建一些功能。 例如
export interface State {
  key: string;
}

export const initialState: State = {
  key: ''
};

export const feature = createFeature({
  name: 'module',
  reducer: createReducer(
    initialState
  )
});

export const {
  name,
  reducer
} = feature;
  1. 结合模块中的所有减速器
import * as fromGreatFeature from './store/great-feature/great-feature.reducer';
import * as fromEntity from './store/entity/entity.reducer';
import * as fromModule from './store/module/module.reducer';


export interface ScheduleState {
  module: fromModule.State; // <- from example
  entity: fromEntity.State;
  greatFeature: fromGreatFeature.State;
}


export const reducers = combineReducers({
  module: fromModule.reducer, // <- from example 
  entity: fromEntity.reducer,
  greatFeature: fromGreatFeature.reducer
});
  1. 制作单独的商店模块或内部模块
export const yourFeature = createFeature<AppState>({
  name: 'yourFeature', // name from interface
  reducer: reducers // combined reducers
});

export const {
  name,
  reducer
} = yourFeature;-----------------
                                |
                                |
@NgModule({                     |
  imports: [                    |
    StoreModule.forFeature(yourFeature),
    EffectsModule.forFeature([Effects, Effects, Effects])
  ],
  exports: [StoreModule, EffectsModule]
})
export class LegendaryStoreModule {}
@NgModule({
  declarations: [
    SomeComponent
  ],
  imports: [
    SharedModule,
    LegendaryRoutingModule,
    LegendaryStoreModule, // <- your store module
  ],
  exports: [

  ]
})
export class YourLegendaryModule {}
  1. 和选择器。 函数createFeature自动生成给你的选择器
export const getSomeThing = createSelector(
  yourFeature.selectYourFeatureModuleState, // <- main feature state
  fromModule.selectSome // <- nested state
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM