简体   繁体   中英

Render products in shopping cart with the number of each product

Below is the array response returned from my API for user's cart:

[
  {
    id: 13,
    user_id: 13,
    product_id: 8,
    product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1'
  },
  {
    id: 14,
    user_id: 13,
    product_id: 8,
    product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1'
  },
  {
    id: 15,
    user_id: 13,
    product_id: 8,
    product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1'
  },
  {
    id: 27,
    user_id: 13,
    product_id: 2,
    product_name: 'Canon 100% Genuine Original Pixma TS3140 AIO Wirel'
  },
  {
    id: 29,
    user_id: 13,
    product_id: 9,
    product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA'
  },
  {
    id: 30,
    user_id: 13,
    product_id: 9,
    product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA'
  },
  {
    id: 31,
    user_id: 13,
    product_id: 9,
    product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA'
  },
  {
    id: 32,
    user_id: 13,
    product_id: 26,
    product_name: 'Viewsonic Viewsonic 3600 Lumens HDMI VGA AV Projec'
  }
]

I need to get the number of times each product appears in the array and then render it. I've tried creating a new Array "renderedCart" and pushing products who don't exist there into it with the number of times they occur. For some reason, the only product in the array is the last one. Here is the function that does this:

useEffect(() => {
  if (cart.length > 0) {
    // At least one product in cart
    cart.map((cartItem) => {
      var count = 0;
      renderedCart.map((cartProduct) => {
        if (cartProduct.product_id === cartItem.product_id) {
          count++;
        }
      });
      if (count === 0) {
        // product not found in rendered cart

        var cartFilter = cart.filter(
          (item) => item.product_id === cartItem.product_id
        );
        var product = cartItem;
        product.count = cartFilter.length;
        updateRenderedCart([...renderedCart, product]);
      }
    });
  }
}, [cart]);

I would suggest reducing the array into an object of product counts by product id.

const counts = cart.reduce((counts, { product_id }) => ({
  ...counts,
  [product_id]: (counts[product_id] || 0) + 1,
}), {});

Example result:

{
  "2": 1,
  "8": 3,
  "9": 3,
  "26": 1
}

 const cart = [ { id: 13, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 14, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 15, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 27, user_id: 13, product_id: 2, product_name: 'Canon 100% Genuine Original Pixma TS3140 AIO Wirel' }, { id: 29, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 30, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 31, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 32, user_id: 13, product_id: 26, product_name: 'Viewsonic Viewsonic 3600 Lumens HDMI VGA AV Projec' } ]; const counts = cart.reduce((counts, { product_id }) => ({...counts, [product_id]: (counts[product_id] || 0) + 1, }), {}); console.log(counts);

Then when you are mapping the cart to be rendered use the item.product_id to look up the item count.

If you are just wanting to render a reduced cart then instead of returning a map of object counts, reduce the cart into an array.

const cartWithQuantities = Object.values(
  cart.reduce((cart, item) => ({
    ...cart,
    [item.product_id]: {
      ...item,
      quantity: (cart[item.product_id]?.quantity || 0) + 1
    },
  }), {})
);

 const cart = [{ id: 13, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 14, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 15, user_id: 13, product_id: 8, product_name: 'Lenovo Ideapad Intel Celeron 1TB HDD 8GB RAM Win 1' }, { id: 27, user_id: 13, product_id: 2, product_name: 'Canon 100% Genuine Original Pixma TS3140 AIO Wirel' }, { id: 29, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 30, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 31, user_id: 13, product_id: 9, product_name: 'Lenovo Ideapad 14inch AMD Quad Core 1TB HDD 8GB RA' }, { id: 32, user_id: 13, product_id: 26, product_name: 'Viewsonic Viewsonic 3600 Lumens HDMI VGA AV Projec' } ]; const cartWithQuantities = Object.values( cart.reduce((cart, item) => ({...cart, [item.product_id]: {...item, quantity: (cart[item.product_id]?.quantity || 0) + 1 }, }), {}) ); console.log(cartWithQuantities);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM