Search code examples
angularngrxngrx-selectors

NGRX: how to call factory selectors from within other selectors


Since NGRX deprecated selectors with props in version 11. and the expected method for using properties is to create factory selectors,

  • how can you nest selectors, or call one from another and pass the state between them?

Prior to the change, with the following two selectors

export const selector1 = createSelector(
   state,
   ( state: FormState, props: {id: string} ) => {
       // Return items whose parent match the given id
       return state.items.filter( item => item.parentId === props.id);
   }
);

export const selector2 = createSelector(
    state
    ( state, FormState, props: { id: string} ) => {
       return state.notes.filter( note => note.parentId === props.id);
    }
)

you could call one of the selectors from another, with the following

export const selector3 = createSelector(
   state,
   ( state: FormState, props: {id: string} ) => {
       // get notes by using an existing selector and passing the state & properties
       const notes = selector2({ storeName: state}, props)
       // do some more logic based on the nested call to a selector
       ...
   }
);

now that factory selectors are the expected format when dealing with properties, selectors now look like the following

export const selector1 = (id: string) => createSelector(
   state,
   ( state: FormState ) => {
       // Return items whose parent match the given id
       return state.items.filter( item => item.parentId === id);
   }
);

export const selector2 = (id: string) => createSelector(
    state
    ( state, FormState ) => {
       return state.notes.filter( note => note.parentId === id);
    }
)
  • given factory selectors, is there a way to call selector2 from within selector1
  • if so, how is the state passed to the nested selector

for example

export const selector3 = (id: string) => createSelector(
   state,
   ( state: FormState ) => {
       // how is the `state` passed to the nested selector call below? 
       const notes = selector2( id)
   }
);

Thank you.


Solution

  • The createSelector function can receive other selectors as arguments.

    So you could do:

    export const selector3 = (id: string) => createSelector(
       state,
       select2(id),
       (state: FormState, filteredNotes ) => {
    
           const notes = filteredNotes;
       }
    );