@ ngrx / store объединяет несколько редукторов из функционального модуля

В настоящее время я работаю над простым тестовым приложением, чтобы узнать больше о @ 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)

Но это дало мне сообщение об ошибке Cannot read property 'упражнения' в консоли. Может быть, кто-то может помочь мне понять, как мне собрать все редукторы из модуля функции и создать для этого правильный селектор.


person jhen    schedule 01.11.2017    source источник


Ответы (2)


Могу привести пример, как я это сделал. Я использовал 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);

модуль / user.module.ts

import { reducers } from './reducers';
@NgModule({
    imports: [
        ...
        StoreModule.forFeature('userModule', reducers)
    ],
     ...
})
export default class UserModule { }
person wheeler    schedule 02.11.2017
comment
Спасибо за ответ. Я попробую это сделать, когда буду дома, но, похоже, именно этого я и пытаюсь достичь. Позже расскажу, сработало ли у меня :) - person jhen; 02.11.2017
comment
Спасибо, чувак, это наконец решило мою проблему с пониманием. Я получил это работать сейчас - person jhen; 03.11.2017
comment
И как мои селекторы функций затем получают доступ к своему текущему состоянию SubFeature? - person Phil; 06.02.2018
comment
export interface State extends fromRoot.State { userModule: UserModuleState; } может кто-нибудь объяснить об этой строке. Я не могу понять - person NicoleZ; 16.08.2019
comment
@NicoleZ Вы расширяете корневое состояние, добавляя к нему состояние функции / модуля. Корневое состояние (может быть пустым) - это состояние, о котором знает каждая функция / модуль и которое должно расширяться. Это помогает? - person wheeler; 16.08.2019

Ваша установка почти верна.

В функции createFeatureSelector вы объявляете функциональный ключ в корне магазина, в данном примере - «упражнения». Итак, вы собираетесь выбрать store.exercises.exercises.id, например, а селектор функций - это просто ярлык для store.exercises.

Однако в вызове StoreModule.forFeature('training', trainingReducers) вы определили «обучение» как корневой ключ для вашего функционального модуля.

Правильная установка может выглядеть так:

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
);

Рекомендуется сохранить ключ функции в переменной вместо того, чтобы жестко его кодировать.

person elobuho    schedule 02.07.2020