如何在效果中访问状态树?(@ ngrx/effects 2.x)

Hon*_*iao 22 typescript ngrx angular

我正在将@ 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 }));
Run Code Online (Sandbox Code Playgroud)

现在在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 }));
Run Code Online (Sandbox Code Playgroud)

Hon*_*iao 25

另一种方式是使用.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 }));
Run Code Online (Sandbox Code Playgroud)


car*_*ant 5

效果不必是类属性。它们也可以是方法。这意味着您可以访问注入到构造函数中的商店。

在撰写此答案时, 我尚不清楚属性声明和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 }));
  }
}
Run Code Online (Sandbox Code Playgroud)

我猜是否这样做是一个好习惯。读取状态(理想情况下,通过组合一个ngrx样式的选择器)听起来很合理,但如果将特定效果所需的所有信息都包含在监听的动作中,则状态会更清晰。