使用商店的坏习惯?
Bad practice to use store in effect?
我有一个 InitAction
,其中包含一些参数,例如个人资料 ID 和更多数据,并且可以使用不同的参数多次调用该操作。
除此之外还有一个 LoadProfileAction
我添加了一个正在监听 InitAction
并触发 LoadProfileAction
.
的效果
问题是,我只想触发 LoadProfileAction
,如果配置文件 ID 与前一个相比发生了变化,所以我认为最好的(?)解决方案是使用 withLatestFrom
使用我的商店并检查当前的个人资料 ID。
但是在一个效果中使用商店感觉不对,因为它似乎违反了通量原理或者不是这样吗?有没有更好的解决方案?谢谢!
更新
现在 NgRX (v12) 提供了自己的运算符来在效果中使用存储。您不再需要 concatMap
、of
、withLatestFrom
这两个解决方案。现在您可以使用 @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.
我有一个 InitAction
,其中包含一些参数,例如个人资料 ID 和更多数据,并且可以使用不同的参数多次调用该操作。
除此之外还有一个 LoadProfileAction
我添加了一个正在监听 InitAction
并触发 LoadProfileAction
.
问题是,我只想触发 LoadProfileAction
,如果配置文件 ID 与前一个相比发生了变化,所以我认为最好的(?)解决方案是使用 withLatestFrom
使用我的商店并检查当前的个人资料 ID。
但是在一个效果中使用商店感觉不对,因为它似乎违反了通量原理或者不是这样吗?有没有更好的解决方案?谢谢!
更新
现在 NgRX (v12) 提供了自己的运算符来在效果中使用存储。您不再需要 concatMap
、of
、withLatestFrom
这两个解决方案。现在您可以使用 @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.