ngrx store subscription not called when state changes

9.3k views Asked by At

I am creating an application with dummy data defined in my service.

In one component, I have the following function that deletes a product:

  removeItem(productId: string) {
      this.cartService.removeItem(productId);
  }

and the service as follows:

  removeItem(productId: string) {
    const itemIndex = this.cart.products.findIndex(el => el.id === productId);
    if (itemIndex > -1) {
      this.cart.products.splice(itemIndex, 1);
      return Observable.of(this.cart)
        .subscribe((cartResponse: Cart) => {
          this.store.dispatch({ type: CART_UPDATE, payload: cartResponse });
        });
    }
  }

(this.cart is the data I have hard coded in the service).

My reducer looks like:

export const cartReducer = (state: Cart = {} as Cart, {type, payload}) => {
  switch (type) {

    case CART_UPDATE:
      // update categories state
      return payload;
    default:
      return state;
  }
};

Then I am subscribing to the cart in one component like:

  ngOnInit() {
    this.store.select('cart').subscribe((cart: Cart) => {
      console.log('here');
      this.numberOfItems = cart.products.length;
    });
  }

I also have in app.module

StoreModule.provideStore({
  cart: cartReducer
}),

The remove function works fine, and the code reaches the reducer function with the correct payload.

The issue is that the subscription callback in the component is called only the first time the component is loaded.

When I call the remove function, the product is indeed removed and the reducer function is called and returning the correct data, but the callback is not called.

Am I missing something?

1

There are 1 answers

4
Teddy Sterne On BEST ANSWER

I think the issue is that the payload you are returning in the reducer has the same object reference as the existing state. Try returning a new object and see if that causes your subscription to be invoked. Like so:

export const cartReducer = (state: Cart = {} as Cart, {type, payload}) => {
  switch (type) {    
    case CART_UPDATE:
      // update categories state
      return { ...payload }; // equivalent to Object.assign({}, payload);
    default:
      return state;
  }
};