Search code examples
ngrxngrx-store

Composing Selectors inside "Extra Selectors" throws: Cannot access 'selectFirstFilteredBook' before initialization


Using a selector inside it sibling throws an error Cannot access 'selectFirstFilteredBook' before initialization. Is it intended behavior and I am missing something or is it a limitation of extraSelectors?

Here is an example:

export const booksFeature = createFeature({
name: 'books',
reducer: createReducer(
initialState,
on(BookListPageActions.search, (state, action) => ({
       ...state,
       query: action.query,
    })),
   ),

extraSelectors: ({ selectQuery, selectBooks }) => ({

selectFilteredBooks: createSelector(
  selectQuery,
  selectBooks,
       (query, books) => books.filter(book => book.title.includes(query)),
     ),

selectFirstFilteredBook: createSelector( //<<<--- Selector that throws error
  selectFilteredBooks,
       (filteredBooks) => filteredBooks[0],
     ),
   }),
});`

If its a not supported behavior, the only solution I see would be to duplicate selectFilteredBooks logic inside selectFirstFilteredBook and that´s just ugly.

Moreover, if described behaviour is not possible it makes impossible creating a decent View Model selector which is a deal breaker.

Does anyone have a solution/workaround?


Solution

  • I hope I can help you. Instead of returning the object with all selectors you can save the selectors in some variables and return the object afterwards. In your example:

    extraSelectors: ({ selectQuery, selectBooks }) => {
      const selectFilteredBooks = createSelector(
        selectQuery,
        selectBooks,
        (query, books) => books.filter(book => book.title.includes(query))
      );
      const selectFirstFilteredBook = createSelector(
        selectFilteredBooks,
        (filteredBooks) => filteredBooks[0],
      );
      return {
        selectFilteredBooks,
        selectFirstFilteredBook
      }
    }
    

    Please let me know if it answers your question!