Я использую Angular 2 с ngrx / store. Я хочу сбросить все состояния магазина при отправке пользователем USER_LOGOUT.

Я прочитал ответ Дэна Абрамова о Как сбросить состояние Redux store?, но я не понял, как правильно написать rootReducer и куда его поставить при использовании ngrx / store.

Или есть другой способ справиться с этим в ngrx / store?

bootstrap(App, [
    provideStore(
      compose(
        storeFreeze,
        storeLogger(),
        combineReducers
      )({
        router: routerReducer,
        foo: fooReducer,
        bar: barReducer
      })
    )
  ]);
25
Hongbo Miao 5 Сен 2016 в 05:47

4 ответа

Лучший ответ

Этот ответ относится к ngrx версии 2. В вопросе есть другой, более свежий ответ, в котором объясняется, как то же самое можно сделать с ngrx версии 4.


compose создает корневой редуктор ngrx.

Аргументы, передаваемые в compose, являются функциями, которые возвращают редуктор - составленный из редуктора, который они сами передают в качестве аргумента. Вы можете составить сброс своего магазина так:

import { compose } from "@ngrx/core/compose";

...

bootstrap(App, [
  provideStore(
    compose(
      storeFreeze,
      storeLogger(),
      (reducer: Function) => {
        return function(state, action) {
          if (action.type === 'USER_LOGOUT') {
            state = undefined;
          }
          return reducer(state, action);
        };
      },
      combineReducers
    )({
      router: routerReducer,
      foo: fooReducer,
      bar: barReducer
    })
  )
]);

Обратите внимание, что это приведет к сбросу всего состояния хранилища, включая router. Если это не то, что вы хотите, вы можете настроить пример.

С введением NgModule начальная загрузка изменилась, но вы по-прежнему передаете составной редуктор provideStore:

import { compose } from "@ngrx/core/compose";
import { StoreModule } from "@ngrx/store";

@NgModule({
    ...
    imports: [
        ...
        StoreModule.provideStore(compose(...))
    ],
    ...
15
cartant 27 Окт 2017 в 11:57

На самом деле это не ответ, но комментарии не позволяют мне его правильно отформатировать. Чтобы добавить к тому, что сказал картант, если вы настраиваете свои типы следующим образом:

export const ActionTypes = {
  LOGOUT:  type('[Environment] Logout of portal'),
  ....
}

Это длинное описание, которое вам следует использовать. Кроме того, если вы назовете свой корневой редуктор rootReducer вместо просто reducer, вы также измените это. Ниже приведен отредактированный пример:

(Я оставил эту функцию в моем корневом редукторе)

const developmentReducer: ActionReducer<State> = compose(...DEV_REDUCERS,
(rootReducer: Function) => {
    return function(state, action) {
      if (action.type === '[Environment] Logout of portal') {
        state = undefined;
      }
      return rootReducer(state, action);
    };
  }, combineReducers)(reducers);
3
Post Impatica 21 Фев 2017 в 04:28

С @ ngrx / store ":" ^ 4.0.3 "это немного отличается, потому что есть небольшие изменения, поэтому мое« чистое состояние »выглядит так

import { ActionReducerMap } from '@ngrx/store';
import { ActionReducer, MetaReducer } from '@ngrx/store';

export const rootReducer: ActionReducerMap<StoreStates> = {
  points: pointsReducer,
  ...
};

export function clearState(reducer: ActionReducer<StoreStates>): ActionReducer<StoreStates> {
  return function(state: StoreStates, action: Action): StoreStates {
    if (action.type === 'CLEAR_STATE') {
      state = undefined;
    }
    return reducer(state, action);
  };
}
export const metaReducers: MetaReducer<StoreStates>[] = [clearState];

А также

import { StoreModule } from '@ngrx/store';
import { metaReducers, rootReducer } from '../root.reducer';

export const imports: any = [
   StoreModule.forRoot(rootReducer, { metaReducers }),
   ...
]
15
Limarenko Denis 20 Сен 2017 в 00:10

В ngrx / store 4.x это можно сделать с помощью метаредукторы. Насколько я понимаю, все действия проходят через метаредукторы, прежде чем будут переданы редукторам функций. Это дает нам возможность сначала изменить / сбросить состояние.

Вот пример.

Это моя функция метаредуктора: если действие имеет тип LOGOUT, состояние повторно инициализируется.

function logout(reducer) {
  return function (state, action) {
    return reducer(action.type === LOGOUT ? undefined : state, action);
  }
}

Ниже вы видите, как настроен метаредуктор вместе с редукторами функций. Если метаредукторов больше 1, то они оцениваются справа налево.

StoreModule.forRoot({rooms: roomReducer, user: userReducer}, {metaReducers: [logout]})

Наконец, у меня также есть @effect, где я перехожу на страницу входа в систему.

@Effect({dispatch: false}) logout: Observable<Action> = 
this.actions$.ofType(LOGOUT)
  .do(() => {
    // ... some more stuff here ...
    this.router.navigate(['/login page'])
});
40
David Bulté 16 Сен 2017 в 06:23