I have a very simple state in my store:
const state = {
records: [1,2,3],
};
I have a selector for records:
export const getRecords = createSelector(getState, (state: State) => state.records));
And what I want now is to have separate selectors for fetching each record by index.
For this purpose I want to create one generic selector with props in this way:
export const getRecordByIndex = createSelector(
getRecords,
(state: State, { index }) => state.records[index]),
);
And after that create a couple of specific selectors e. g.:
export const getFirstRecord = createSelector(
getRecordByIndex(/* somehow pass index = 0 to this selector */),
(firstRecord) => firstRecord),
);
But I didn't find any mention how to pass parameters to selectors with props when we use them inside createSelector method. Is it possible?
From this blog post: https://medium.com/angular-in-depth/ngrx-parameterized-selector-e3f610529f8
As of NgRx 6.1 selectors also accepts an extra props argument. Which
means you can now define a selector as the following:
export const getCount = createSelector(
getCounterValue,
(counter, props) => counter * props.multiply
);
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: 2 })
);
Ah ... but rereading your question, you are asking then how to build another selector that uses this selector? The above-linked article suggests building a factory function.
I am using "@ngrx/entity": "7.2.0",
and I can see that props are passed to each selector, for example in my component I am calling:
this.isActive$ = this.store.pipe(select(fromClient.isActive, { id: 'someid' }));
And then in my reducer I have the following:
export const getClientState = createFeatureSelector<ClientState>('client');
export const getClient = createSelector(
getClientState,
(state, props) => {
// do something with props.id to get the client then:
return state;
}
);
export const isActive: = createSelector(
getClient, // props are passed to here
(state: any) => { // i don't add the props argument here, as i don't need them
return state.isActive;
}
);
You could use the projector function:
export interface Record {
// Some sort of record interface
}
export interface State {
records: Record[];
}
export const getRecords = createSelector(
getState,
(state: State): Record[] => state.records)
);
export const getRecordByIndex = createSelector(
getRecords,
(records: Record[], { index }) => records[index]),
);
export const getFirstRecord = createSelector(
getRecords,
(records: Record[]) => getRecordByIndex.projector(records, { index: 0 })
);
With fixed parameters for the selector it works fine:
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: 2 })
);
but what's about dynamic parameters:
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: this.getMultiplier() })
);
getMultiplier() {
...
return myUser.multiplier + magicFactor;
}
that did not work in my app :-( (NgRx version 8)