Search code examples
angularngrxangular8ngrx-storengrx-entity

@ngrx/entity `Cannot read property 'ids' of undefined` when using together with @ngrx/store? already accounting for custom ids when defining adapter


I have looked at the 2 other posts regarding this, the one with the wrapping around the larger state does not apply whilst the other one with registering multiple forFeature -- I have done some testing around that and even if I import it before or after the forRoot(reducers) in my app.module, it makes no difference.

I'm sure I'm missing something obvious around the configuration.

My configuration:

export const orderAdapter: EntityAdapter<IOrder> = createEntityAdapter<IOrder>({
  selectId: (order: IOrder) => order._id
});

export interface AllOrdersState extends EntityState<IOrder> {}

export const initialState: AllOrdersState = orderAdapter.getInitialState({
  ids: [],
  entities: {}
});

export const OrdersState = createFeatureSelector<AllOrdersState>('orders');

export const {
  selectIds,
  selectEntities,
  selectAll,
  selectTotal
} = orderAdapter.getSelectors(OrdersState);

My actual reducer:


export function ordersReducer(
  state: AllOrdersState = initialState,
  action: actions.OrdersActions
) {
    case actions.CREATE_MANY: {
      console.log(action.orders);
      return orderAdapter.addMany(action.orders, state);
    }
}

I register in my Order.Module as:

    StoreModule.forFeature('orders', ordersReducer),

My main reducer map:

const reducers: ActionReducerMap<AppState> = {
  order: orderReducer,
  admin: adminReducer,
  tlabs: tlabsReducer,
  reports: reportsReducer,
  settings: settingsReducer,
  orders: ordersReducer
};

Then the main import in app.module:

    StoreModule.forRoot(reducers),

Trying to read the entities:

Constructor:

 private store: Store<AppState>

Actual function:

this.store
      .select(ordersReducer.selectAll)

Where that import is taken from:

import * as ordersReducer from '../../../../../store/reducers/orders.reducer';

Solution

  • It looks like it's trying to read from OrdersState before it has been initialized. Your reducer doesn't actually return the default state in order to initialize it; At least you don't seem to, at the code you present.

    Make your reducer return the default state.

    export function ordersReducer(
      state: AllOrdersState = initialState,
      action: actions.OrdersActions
    ) {
        switch(action.type) {
            case actions.CREATE_MANY: {
              console.log(action.orders);
              return orderAdapter.addMany(action.orders, state);
            }
    
            default: { 
              return state // Here you should return the default state
            }
        }
    }