2

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.

Edward
  • 1,076
  • 1
  • 12
  • 24

1 Answers1

1

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;
   }
);
The Fabio
  • 5,369
  • 1
  • 25
  • 55
  • thank you for the response. I am using this approach in some other selectors. but I'm wondering if there is a way to call the selector other than including it as an argument? i.e. to allow applying conditional business logic prior to calling the selector. i.e. checking if the `id` argument is valid prior to calling the selector... – Edward Dec 17 '21 at 13:38
  • not sure if you get significant performance improvement from conditionally applying selectors, they are very lean functions. You could call all of the selectors you need as arguments, than use their values selectively. – The Fabio Dec 19 '21 at 21:41