Search code examples
angulartypescriptrxjsngrx

use pipe in ngrx selector


I want a memoized selector which includes a rxjs transformation in its projector function. Tried like that to get arrays of FunctionProps per group of FunctionProps.Category of an FunctionProps[] array which is selected by memoized selector selectFunctionProperties:

   export const selectGroupedFunctionProperties = createSelector(
    selectFunctionProperties,
    (f) => from(f).pipe(
        groupBy((v: FunctionProps) => v.Category),
        mergeMap(group => group.pipe(toArray())),
        toArray()
    )
);

As you can see I used a 'from' to get a pipeable observable from the source FunctionProps[] array. This of course is not a good idea, because the selectGroupedFunctionProperties selector now is an observable of observable in the consuming component.

Is there an approach to have the pipe in a memoized selector instead of using the pipe in the component this.store.select(selectFunctionProperties).pipe(...) ?

I want to be able to combine selectors and keep rxjs code out of components.

Otherwise is it a valid pattern to use a pipe in a selector (so I cannot avoid implementing groupBy for array with type script as pure function inside the selector)?

EDIT I changed the selector using the pipe operator directly:

export const selectGroupedFunctionProperties = pipe(
    select(selectFunctionProperties),
    concatMap(functions => functions),
    groupBy(v => v.Category),
    mergeMap(group => group.pipe(toArray())),
    toArray(),
);

In the component I receive the Functionprops[][] array with a pipe instead of the select:

groupedFunctions$ = this.store.pipe(selectGroupedFunctionProperties);

Solution

  • You have the option to export a pipe by itself (without createSelector):

    export const selectGroupedFunctionProperties = pipe(
      select(selectFunctionProperties),
      groupBy((v: FunctionProps) => v.Category),
      mergeMap(group => group.pipe(toArray()))
      // I'm not quite sure, but I don't think you need the 'toArray'-operator
    );
    

    Have a look at the docs too for this: https://ngrx.io/guide/store/selectors#breaking-down-the-basics