使用商店的坏习惯?

Bad practice to use store in effect?

我有一个 InitAction,其中包含一些参数,例如个人资料 ID 和更多数据,并且可以使用不同的参数多次调用该操作。

除此之外还有一个 LoadProfileAction 我添加了一个正在监听 InitAction 并触发 LoadProfileAction.

的效果

问题是,我只想触发 LoadProfileAction,如果配置文件 ID 与前一个相比发生了变化,所以我认为最好的(?)解决方案是使用 withLatestFrom使用我的商店并检查当前的个人资料 ID。

但是在一个效果中使用商店感觉不对,因为它似乎违反了通量原理或者不是这样吗?有没有更好的解决方案?谢谢!

更新

现在 NgRX (v12) 提供了自己的运算符来在效果中使用存储。您不再需要 concatMapofwithLatestFrom 这两个解决方案。现在您可以使用 @ngrx/effects 库中的 concatMapFrom,如下所示:

import { concatLatestFrom } from '@ngrx/effects';

...

createEffect(() => this.actions$.pipe(
  ofType(getSelectedBookDetails),
  concatLatestFrom(action => this.store.select(getSelectedBookId)),
  switchMap(([action, selectedBookId]) => this.bookService.getDetails(selectedBookId).pipe(
    map(...),
    catchError(...)
  )
);

2020/08/19 的旧答案

回答这个问题有点晚了,但也许这对外面的人有帮助。我几乎每天都使用 NgRX,我想分享我的个人见解。

您绝对可以在效果中使用商店。您只需要通过构造函数导入商店(因为它是依赖注入树的一部分),然后您可以在相关效果中使用 withLatestFrom RxJS 运算符。如果您阅读官方文档,您可能会在 effects documentation 上看到一条注释,上面写着

Note: For performance reasons, use a flattening operator in combination with withLatestFrom to prevent the selector from firing until the correct action is dispatched.

因此,理想情况下,您可以按以下方式使用商店:

createEffect(() => this.actions$.pipe(
  ofType(getSelectedBookDetails),
  concatMap(action => of(action).pipe(
    withLatestFrom(this.store.select(getSelectedBookId))
  )),
  switchMap(([action, selectedBookId]) => this.bookService.getDetails(selectedBookId).pipe(
    map(...),
    catchError(...)
  )
);

其中 getDetails() 是一个 Angular http 请求,returns 是一个 Observable,getSelectedBookId 是一个 NgRX 选择器。至少我希望你能知道如何使用它,并且在效果中使用它完全不是问题。

你也可以确定effect是在reducer执行完之后执行的。 This order is guaranteed.