Search code examples
javascriptreactjsreduxredux-toolkit

How get Total Price ADD and REMOVE items in Cart Page using Redux and React js


I am trying to get total price of items added and removed in Cart, but total just increase and no decrease when remove one item.

I'm working with reducer and I am almost sure that I've implemented here the logic but I'm very stuck in this trouble.

This is my code reducer in CartRedux.js

const cartSlice = createSlice({
  name: "cart",
  initialState: {
    products: [],
    quantity: 0,
    total: 0,
  },
  reducers: {
    addProduct: (state, action) => {
      state.quantity += 1;
      state.products.push((product) => product._id === action.payload);
      state.total += action.payload.price * action.payload.quantity;
    },
    clearCart: (state) => {
      state.products = [];
    },
    deleteProductStart: (state) => {
      state.isFetching = true;
      state.error = false;
    },
    deleteProductSuccess: (state, action) => {
      state.isFetching = false;
      state.quantity -= 1;
      state.products.splice(
        state.products.findIndex((item) => item._id === action.payload),
        1
      );
      //agregar aquí la función para restar el total en el RESUMEN DE COMPRA
    },
    deleteProductFailure: (state) => {
      state.isFetching = false;
      state.error = true;
    },
  }
});

Solution

  • The deleteProductSuccess case reducer isn't computing/recomputing a total, but instead is only adjusting the total quantity.

    Both quantity and total are what would be considered derived "state", meaning these are easily computed values from actual state, and don't generally belong as part of the state as it's considered a React anti-pattern. The suggestion here is to instead store just the products array and compute the derived state the cart.products array.

    Example:

    const cartSlice = createSlice({
      name: "cart",
      initialState: {
        products: [],
      },
      reducers: {
        addProduct: (state, action) => {
          const item = state.products.find((product) => product._id === action.payload.id);
    
          if (item) {
            item.quantity += action.payload.quantity;
          } else {
            state.products.push(action.payload);
          }
        },
        clearCart: (state) => {
          state.products = [];
        },
        deleteProductStart: (state) => {
          state.isFetching = true;
          state.error = false;
        },
        deleteProductSuccess: (state, action) => {
          state.isFetching = false;
          state.products.splice(
            state.products.findIndex((item) => item._id === action.payload.id),
            1
          );
        },
        deleteProductFailure: (state) => {
          state.isFetching = false;
          state.error = true;
        },
      }
    });
    
    // Note: the selector functions need to access the correct state from root.
    // This is dictated by how you combine reducers and structure the reducer tree.
    // This is just an example since I've no idea what the overall state
    // looks like, it assumes `cart` is a root reducer/state property.
    export const cartQuantitySelector = (state) => state.cart.products.reduce(
      (quantity, item) => quantity + item.quantity,
      0
    );
    export const cartTotalSelector = (state) => state.cart.products.reduce(
      (total, item) => total + item.price * item.quantity,
      0
    );
    

    Getting the cart quantity & cart total in component

    import { useSelector } from 'react-redux';
    import { cartQuantitySelector, cartTotalSelector } from '../path/to/CartRedux';
    
    ...
    
    const cartQuantity = useSelector(cartQuantitySelector);
    const cartTotal = useSelector(cartTotalSelector);
    ...