Как получить доступ к дереву состояний в эффектах? (@ngrx/effects 2.x)
Я обновляю @ngrx/effects от 1.x до 2.x
В 1.x у меня есть доступ к дереву состояний:
constructor(private updates$: StateUpdates<AppState>) {}
@Effect() bar$ = this.updates$
.whenAction(Actions.FOO)
.map(obj => obj.state.user.isCool)
.distinctUntilChanged()
.filter(x => x)
.map(() => ({ type: Actions.BAR }));
Теперь в 2.x это только дает мне действие. Есть ли способ получить доступ к дереву состояний? Или мне следует избегать такого использования, потому что это не очень хорошая практика?
constructor(private actions$: Actions) {}
@Effect() bar$ = this.actions$
.ofType(ActionTypes.FOO)
.map((obj: any) => {
console.log(obj); // here is action only
return obj.state.user.isCool // so it is wrong here
})
.distinctUntilChanged()
.filter(x => x)
.map(() => ({ type: ActionTypes.BAR }));
Ответы
Ответ 1
Другой способ - использовать .withLatestFrom(this.store)
. Таким образом, полный код:
constructor(
private actions$: Actions,
private store: Store<AppState>
) {}
@Effect() bar$ = this.actions$
.ofType(ActionTypes.FOO)
.withLatestFrom(this.store, (action, state) => state.user.isCool)
.distinctUntilChanged()
.filter(x => x)
.map(() => ({ type: ActionTypes.BAR }));
Ответ 2
Эффекты не должны быть свойствами класса; они также могут быть методами. Это означает, что вы можете получить доступ к хранилищу, который был введен в конструктор.
Во время написания этого ответа семантика объявлений свойств и параметры конструктора public
/private
мне не поняли. Если свойства объявлены после конструктора, они могут получить доступ к членам public
/private
, объявленным через параметры конструктора, - поэтому вам не нужно объявлять свои эффекты как функции.
В загруженном хранилище вы можете использовать оператора типа mergeMap
для получения состояния и объединения его с полученным вами обновлением:
@Effect()
bar$(): Observable<Action> {
return this.actions$
.ofType(ActionTypes.FOO)
.mergeMap((update) => this.store.first().map((state) => ({ state, update })))
.map((both) => {
// Do whatever it is you need to do with both.update and both.state.
return both.update;
})
.distinctUntilChanged()
.filter(x => x)
.map(() => ({ type: ActionTypes.BAR }));
}
}
Я думаю, что это хорошая практика - это мнение. Чтение состояния - в идеале, составление селектора ngrx-стиля - звучит разумно, но было бы более чистым, если бы вся информация, необходимая для определенного эффекта, была включена в действие, которое оно слушало.