0
votes

I am trying to implement a function called 'addToCart' which is responsible for adding products inside a 'cartItems' state whenever user clicks on a specific product. I am able to add as many products as i want . But whenever i click on a specific product, i want to change its qty if it is already inside my cart instead of adding duplicate items. I want to increase items qty no matter how many times i click the specific product. I have uploaded some of my code to make it more concise.

initialState

  const initState = {
    cartItems: []
    }

cartReducer

case CART_ADD_ITEM:
  const item = action.payload;
  const existItem = state.cartItems.find((x) => x.product === item.product);
  if (existItem) {
    return {
      ...state,
      cartItems: state.cartItems.map((x) =>
        x.product === existItem.product ? { ...item, qty: item.qty + 1 } : x
      ),
    };
  } else {
    return {
      cartItems: [...state.cartItems, item],
    };
  }

cartActions

export const addToCart = (productId, qty) => async (dispatch, getState) => {
  try {
    const { data } = await Axios.get(`/api/products/${productId}`);
    dispatch({
      type: CART_ADD_ITEM,
      payload: {
        name: data.name,
        price: data.price,
        product: data._id,
        qty,
      },
    });
  } catch (error) {
    console.log(error.response);
  }
};

productComponent

import React from "react";
import { useDispatch } from "react-redux";
import { addToCart } from "../actions/cartActions";
const Product = ({ product, qty }) => {
  const dispatch = useDispatch();
  const addToCartHandler = () => {
    dispatch(addToCart(product._id, qty));
  };
  return (
    <div className="product-card" onClick={addToCartHandler}>
      <h3>{product.name}</h3>
      <p>{product.price}</p>
    </div>
  );
};

export default Product;
1

1 Answers

0
votes

Have taken a close look on the code. The implementation seems make sense. I have just added two things in the cardReducers.js

  1. wrap the return object using (). If you are doing using the ? : operator and the short hand syntax of map, not sure if the compiler will work properly to know that you want to return an object
  2. for the else case, add the ...state for in case you have more properties in the future.
case CART_ADD_ITEM:
  if (existItem) {
    const isCurrentlyExist =  x.product === existItem.product 

    return {
      ...state,
      cartItems: state.cartItems.map(x => (isCurrentlyExist ? { ...item, qty: item.qty + 1 } : x)
    };
  } else {
    return {
      ...state,   //if you have other state in the future
      cartItems: [...state.cartItems, item],
    };
  }