如何使用带参数的选择器从效果中的 ngrx 存储 select

how to select form ngrx store within an Effect using a slector with parameters

我需要构建一个 Effect 并且我需要一个来自商店的值,问题是选择器是一个带参数的选择器。

遵循示例代码:

        @Effect()
      ExampleEffect$ = this.actions$.pipe(
        ofType(
          ActionTypes.SOMETHING
        ),
        map((action: Somthing) => action.payload.myParameter),
// HERE I NEED THE PARAMETER TO PERFROM THE SELECTION
        withLatestFrom(this.store.pipe(select(selectorWithParamter(myParameter))),
        map((value) => /* do somthing with the array [myParameter, valueSelected from sotre]*/)

您可以在创建选择器时编写一个箭头函数来传递参数。

export const getAlbumById = (collectionId: number) => createSelector(getAlbumEntities, entities => entities[collectionId]);

更多示例

//效果

@Effect({ dispatch: true })
  upsertAlbum$ = this.actions$.pipe(
    ofType(AlbumActionTypes.UpsertAlbum),
    map((action: any) => action.payload),
    mergeMap(({ album }) =>
      this.store.pipe(
        select(selectAlbumIfExists(album.id)),
        first(),
        map(isAlbumHasName => [album, isAlbumHasName])
      )
    ),
    filter(([album, isAlbumHasName]) => !isAlbumHasName),
    map(([album]) => new LoadAlbum({ album }))
  );

// 选择器

export const selectAlbumIfExists = (id: string) =>
  createSelector(
    selectAlbumsEntities,
    entities => !!(entities[id] && entities[id].name)
  );

为什么不使用 props 对象?

https://ngrx.io/guide/store/selectors#using-selectors-with-props

您可以创建特定的选择器并在调用 withLatestFrom 时使用它们。

 approve$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(myactions.approve),
      withLatestFrom(this.store.select(selectReference), this.store.select(selectWork)),
      switchMap(([_, reference, work]) => this.service.approve(reference, work)),
      map(() => actions.approveSuccess())
    );
  });

按照上面的建议,尝试使用选择器。就我而言,

selectReference

selectWork

是 NGRX 选择器,代码如下所示:

//create slice
const requestState= createFeatureSelector<IRequestState>(feature);

//get exactly what you need from the state, not extra stuff
export const selectReference= createSelector(requestState, (state) => state?.reference);

export const selectWork= createSelector(requestState, (state) => state.Work);

保持干净,不要重复选择代码。我怀疑您是否需要带参数的选择器。尝试在选择器中获取列表并通过另一个选择器获取参数。在 switchMap 函数中执行逻辑(或者任何最适合你的函数,mergeMap 或 concatMap)

andreisrob的建议很好。下面提供了一个完整的工作示例。这显示了效果如何使用需要参数的选择器中的值。

updateQuestionnaireTranslationValue$ = createEffect(() => this.actions$.pipe(
    ofType(QuestionnaireTranslationsUpdateValueAction),
    concatMap((action) => {
        this.store.dispatch(GlobalLoadingStartedAction({ message: "Updating translation value ..."}));

        const props = { formId: action.payload.formId, langId: action.payload.translationLanguageId};
        const update$ = this.store.pipe(
            select(selectQuestionnaireTranslationResourceCount, props),
            first(),
            concatMap(translatableCount => {
                const updateRes$ = this.questionnaireService.updateTranslation(action.payload, translatableCount).pipe(
                    tap(() => this.store.dispatch(GlobalLoadingEndedAction())),
                    catchError(err => {
                        this.store.dispatch(GlobalLoadingEndedAction());
                        this.logger.logErrorMessage("Error updating translation value: " + err);
                        this.snackBar.openError("Failed to update translation value");

                        this.store.dispatch(QuestionnaireTranslationsUpdateValueCancelledAction());
                        return of(null);
                    })
                );
                return updateRes$;
            })
        );
        return update$.pipe(map(count => ({ value: action.payload, totalCount: count } )));
    }),
    map((payload: ({ value: QuestionnaireTemplateTranslationUpdateValue, totalCount: number })) => {
        return QuestionnaireTranslationsUpdateValueDoneAction({ payload });
    }))
);