Search code examples
angularngrxngrx-entity

NgRx EntityState - Can we use EntityState on a state object property


Continuing with my new journey into NgRx, I just discovered EntityState, and if I am understanding, and trying to use it correctly, it covers all the "collection manipulation" operations I need to do for me!

I have followed this excellent tutorial, with the one small difference where I want to (if it is possible) to use an EntityState for a property of my state object, as opposed to extending it to be the whole state object, as in the linked example). I have done this to match my existing data, and to allow perhaps another list property that is also a EntityState (once again if it can be used this way).

I have replaced what was an array of objects in one of my feature state objects, but having trouble with a select.

I have a simple version of this here.

Following this example, the state is for feature1, which for simplicity I have just put into a folder rather than a separate module.

My application has existing classes where I serialise in data from the server.

I have put these into the freature1.reducers.ts file..

 export class BookModel {
      public id : string;
      public title: string;
    }

 /** Serialised in from the backend */
 export class LibraryBackendModel {
      books: Array<BookModel>;
    }

So I declare interfaces for the state I want to store, and it is this Array<BookModel> I hope I can replace with EntityState

So, the feature state, I have the following (in the same file)...

export interface LibraryState {
  isOpen : boolean,
  books: EntityState<BookModel> // <----- now using EntityState instead of an array

  // Maybe other collections to come
}

I have a single action getLibrarySuccess which is triggered when new data comes in from the server, and in the reducer file, I use the helper method updateBookList which will use all the various methods on the EntityAdapter to do updates (not included, but thats where they would be).

So far, everything seems fine..

Now finally, (where the problem is) is in feature1.component.ts, where I want to subscribe to the selector getAllBooks

 this.store.pipe(select(fromLibrary.getAllBooks),
      ).subscribe(
        books => this.libaryModel.books = books
      );

Here, I can see the IDE reporting a problem:

enter image description here

The error being....

Type '(state: EntityState<BookModel>) => BookModel[]' is not assignable to type 'BookModel[]'.

So, it appears there is something wrong with my selector...

export const getAllBooks = createSelector(
   getFeature1State,
   state => fromFeature1.getBooks
 );

But I am not sure how to fix this, of what I am doing wrong. The fromFeature1.getBooks is a reference to the booksAdapter.getSelectors().selectAll; from the EntityAdapter. I am assuming I need to somehow use a selector from this EntityAdapter to get my updates and state, but I am just not sure.


Solution

  • I found my problem, I just needed to pass in the state.books as below...

    export const getAllBooks = createSelector(
       getFeature1State,
       state => fromFeature1.getBooks(state.books) <--- pass in state.books
    );