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?
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(),
],
};
Question 1:
i think you can do it as before (Tim's Versin) and don't need the interop package at all if you use ngrx v16. just call the signal to select from the store:
customer$ = store.select(selectCustomer(id())
and if you want to get a signal back from the store directly just use
customer = store.selectSignal(selectCustomer(id())
if you can't use ngrx v16 then you need to use the interop package like you did.
Question 2
Why do you want memoization for the selectorFactory? In your example all "source selectors" are already memoized. So the projector function just get's called if one of source selectors emit a new value and respect the id you used to return the calculated value. The created selector is also memoized so i don't know why you should memoize the factory function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With