How can I pass a parameter to a @ngrx/component-store selector?

4.4k Views Asked by At

Is there a way (or is it even appropriate) to pass a parameter to @ngrx/component-store selector? I was excited about component-store because effects and updaters can take an Observable as a parameter. This means that that Observable does not have to be subscribed to in a component. But there is not appeared to be a way to use an Observable as a parameter to a selector.

4

There are 4 best solutions below

2
Joseph Genchik On
 selectMovie(movieId: string) {
    return this.select((state) => state.movies.find(m => m.id === movieId));
 }

I still wonder how to pass movieId as an Observable and return values from selector when movieId or state was modified.

0
Andrei Gătej On

Judging by one of the signatures:

  select<R, S1>(
    s1: Observable<S1>,
    projector: (s1: S1) => R,
    config?: SelectConfig
  ): Observable<R>;

I think you can achieve what you're looking for by doing:

select(observable1$, () => {})

You can have use more than one observable, as long as the last arguments are (in this order) either the projectioFn and configObject or only the projectionFn.

0
Joseph Genchik On

What I was trying to do is to pass an Observable as a parameter into a selector and get Observable back when the parameter or the State would change. I think I did get it to work. Here is the code snippet

readonly widgets$: Observable<Widget[]> = this.select(state => state.widgets);

widgetsByColor2$(color$: Observable<string>) { 
    return combineLatest(color$, this.widgets$).pipe(
        tap(([color, widgets]) => {
            console.log('color:', color);
            console.log('widgets:', widgets);
         ),
         map(([color, widgets]) => widgets.filter(widget => widget.color == color))
    );
}
1
Michael Kang On

You can create selectors that take parameters:

export const widgetsByColor = createSelector(
   (t: Widget[], props: { color: string }) => t.widgets, (state, props) => {
       return t.widgets.filter(w => w.color == props.color)[0];
   }
);

Use like this:

this.store
  .select(t => widgetsByColor(t, { color: 'blue' }))
    .subscribe(t => {
       ...
    }
)

It is not recommended to take observables as parameters (although you could) as it hinders Memoization as an optimization.