ngrxngrx-store

How to pass an Angular Signal value to an NgRx selector


With regard to NgRx v16 new with Angular Signals, given:

export const selectCustomer = (id: string) =>
  createSelector(selectCustomers, (customers) => customers[id]);

(common expression; taken from Tim Deschryver's blog-post on how to do this with NgRx, up to v15)

Question 1, how should this be done when I have a Signal<string> for id?

FYI, currently I keep the selector as-was and use Angular's toSignal/toObservable, which seems like a bad detour:

import { toSignal, toObservable } from '@angular/core/rxjs-interop'
…
let id: Signal<string>;
…
const customer$ = toSignal(toObservable(id).pipe(
  switchMap(id => store.select(selectCustomer(id)))
));

Also, toObservable requires an injection context, so there are limitations where it can be used in the code.


And regarding memoization like

import * as _ from "lodash";
…
export const selectCustomer = _.memoize((id: string) =>
  createSelector(selectCustomers, (customers) => customers[id])
);

Question 2, will such manual memoization then become unnecessary?


Solution

  • With set withComponentInputBinding in appConfig I got it to work with using computed.

    // books.component.ts
    
    export class BookDetailsComponent {
      private store = inject(Store);
    
      id = input<string>();
      book = computed(() => this.store.selectSignal(selectBook(this.id()))());
    }
    
    // app.config.ts
    
    export const appConfig: ApplicationConfig = {
      providers: [
    provideRouter(
      routes,
      withComponentInputBinding() // route id parameter => to id input signal
    ),
    provideStore(reducers, { metaReducers, runtimeChecks }),
    provideEffects(effects),
    provideHttpClient(),
      ],
    };