J'ai un état très simple dans mon magasin:
const state = {
records: [1,2,3],
};
J'ai un sélecteur pour les enregistrements:
export const getRecords = createSelector(getState, (state: State) => state.records));
Et ce que je veux maintenant, c'est avoir des sélecteurs séparés pour récupérer chaque enregistrement par index. À cette fin, je veux créer un sélecteur générique avec des accessoires de cette manière:
export const getRecordByIndex = createSelector(
getRecords,
(state: State, { index }) => state.records[index]),
);
Et après cela, créez quelques sélecteurs spécifiques e. g.:
export const getFirstRecord = createSelector(
getRecordByIndex(/* somehow pass index = 0 to this selector */),
(firstRecord) => firstRecord),
);
Mais je n'ai trouvé aucune mention sur la façon de passer des paramètres aux sélecteurs avec des accessoires lorsque nous les utilisons dans la méthode createSelector. C'est possible?
De cet article de blog: https://blog.angularindepth.com/ngrx-parameterized-selector-e3f610529f8
Depuis NgRx 6.1, les sélecteurs acceptent également un argument d'accessoires supplémentaires. Ce qui signifie que vous pouvez maintenant définir un sélecteur comme suit:
export const getCount = createSelector(
getCounterValue,
(counter, props) => counter * props.multiply
);
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: 2 })
);
Ah ... mais en relisant votre question, vous vous demandez alors comment construire un autre sélecteur qui utilise ce sélecteur? L'article ci-dessus propose de créer une fonction d'usine.
J'utilise "@ngrx/entity": "7.2.0",
et je peux voir que les accessoires sont passés à chaque sélecteur, par exemple dans mon composant que j'appelle:
this.isActive$ = this.store.pipe(select(fromClient.isActive, { id: 'someid' }));
Et puis dans mon réducteur j'ai les éléments suivants:
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;
}
);
Vous pouvez utiliser la fonction projecteur:
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 })
);
Avec des paramètres fixes pour le sélecteur, cela fonctionne bien:
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: 2 })
);
mais qu'en est-il des paramètres dynamiques:
this.counter = this.store.pipe(
select(fromRoot.getCount, { multiply: this.getMultiplier() })
);
getMultiplier() {
...
return myUser.multiplier + magicFactor;
}
cela ne fonctionnait pas dans mon application :-( (NgRx version 8)