How to get access of the state tree in effects? (@ngrx/effects 2.x)

假如想象 提交于 2019-11-27 14:31:56

问题


I am updating @ngrx/effects from 1.x to 2.x

In 1.x I have access of state tree in effect:

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

Now in 2.x, it only gives me action. Is there still a way to get access of the state tree? Or should I avoid using like this because it is not a good practice?

  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:


Another way is using .withLatestFrom(this.store). So the complete code is:

  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:


Effects don't have to be class properties; they can be methods, too. Which means you can access a store that's injected into the constructor.

At the time of writing this answer, the semantics of property declarations and public/private constructor parameters were not clear to me. If properties are declared after the constructor, they can access the public/private members declared via constructor parameters - so you don't have to declare your effects as functions.

With the injected store, you should be able to use an operator like mergeMap to get the state and combine it with the update you received:

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

Whether or not doing this is good practice is a matter of opinion, I guess. Reading the state - ideally by composing an ngrx-style selector - sounds reasonable, but it would be cleaner if all of the information you needed for a particular effect was included in the action to which it was listening.



来源:https://stackoverflow.com/questions/39565811/how-to-get-access-of-the-state-tree-in-effects-ngrx-effects-2-x

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!