Angular 9 — NGRX Как зарегистрировать «глобальный» редуктор

#angular #ngrx

#angular #ngrx

Вопрос:

Допустим, у меня есть состояние AnimalState , которое выглядит следующим образом:

 {
  cats: Cat[];
  dogs: Dog[];
}
  

Вот как определяются редукторы :

 export const catsReducer = createReducer([],
  on(AnimalAction.loadCats,
    (state, { cats }) => {
      return {
        ...state,
        cats
      };
    }),
);

export const dogsReducer = createReducer([],
  on(AnimalAction.loadDogs,
    (_, { dogs }) => {
      return dogs;
    }),
);

export const reducers: ActionReducerMap<AnimalState> = {
  cats: catsReducer,
  dogs: dogsReducer,
};
  

Затем я внедряю редукторы в свой пользовательский модуль с помощью InjectionToken, такого как :

 const reducerToken = new InjectionToken<ActionReducerMap<AnimalState>>(
'ANIMAL_REDUCERS', 
{ factory: () => reducers });
StoreModule.forFeature("animal", reducerToken),
  

Мой вопрос в том, как я могу создать и зарегистрировать редуктор, который будет использовать оба cats и dogs значения.

Ответ №1:

Ну, вы хотели бы разделить редуктор и начальные состояния:

 const initialCatState: Cat[] = []


export const catsReducer = createReducer(initialCatState,
  on(CatAction.update,
    (state, { cats }) => {
      return cats;
    }),
);


const initialDogState: Dog[] = []


export const dogsReducer = createReducer(initialDogState,
  on(DogAction.update,
    ((state: Dog[]), { dogs }) => {
      return dogs;
    }),
  on(DogAction.add,
    ((state: Dog[]), { dog }) => {
      return [...dogs, dog];
    }),
);
  

А затем зарегистрировать две функции:

 StoreModule.forFeature("cats", catsReducer),
StoreModule.forFeature("dogs", dogsReducer),
  

и выбрать

 export const selectCats = createFeatureSelector('cats');
export const selectDogs = createFeatureSelector('dogs');
  

Комментарии:

1. У меня была бы такая же проблема в одном редукторе, я не смог бы получить доступ к state.cats amp; state.dogs, если я не ошибаюсь?

2. Ну, в конце дня действительно есть только одно хранилище, остальное печатается. Вышесказанное создаст одно хранилище с двумя объектами, state.dogs и state.cats селекторы всегда должны указывать на корень вашего хранилища.

3. селекторы должны быть примерно такими: const selectCats = createFeatureSelector('cats') вместо выбора в редукторе, как вы делаете. редукторы всегда должны возвращать состояние и обновлять свойства синхронно.

4. В редукторе вы хотите реагировать на addCats или updateCats . затем вы хотите return { ...state, cats: action.cats } передать новые данные в действии

5. Кроме того, вы хотите, чтобы они были как можно более плоскими, поэтому избегайте Animals => Cats, Dogs , вместо этого регистрируйте Cats и Dogs на корневом уровне, если это возможно