Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

UseState React hook: updating state is not consistent

I’m trying to build a shopping cart. Just about an hour ago I created another post with a similar problem I was running into, and that problem was solved and I was able to implement that properly.

In this shopping cart, I will display all the items in the cart on one side of the page and display the order details/pricing on the other side. Here is a visual of what I have:

Image of shopping cart, currently.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

As seen in the picture, with each item, I should be able to update the quantity (using the dropdown) and remove the item if necessary (the X sign on each item). My last question was regarding an issue where when I updated the dropdown (quantity) on an item, the price value of that specific item would not update. It seems that I was not properly updating the state, and I have since gotten that issue fixed.

The issue I’m running into now is that when I update the quantity on one of the items, the order summary should also update. I am using the same item (cart) to calculate values in both.

It is important to note that I only run into this issue when I try to update the quantity of an item. When I remove an item, the order summary changes appropriately. It only doesn’t work when I try to change the quantity.

Here is the code for the component that includes the list and the order summer (titled OuterCart):

import React, { useState } from 'react';
import CartItem from './CartItem';
import CartOrder from './CartOrder';

const OuterCart = () => {
  const items = [
    {
      name: 'Boardwalk view',
      quantity: 3,
      finish: 'Non-matted',
      size: '4x8',
      price: 19.99,
      id: 0,
    },
    {
      name: '2 Boardwalk view',
      quantity: 1,
      finish: 'Matted',
      size: '3x6',
      price: 20.99,
      id: 1,
    },
    ... // there are more items
  ]
  
  const [cart, setCart] = useState(items);

  function removeItem(id) { // function run when I click the X
    const newCart = cart.filter((item) => item.id !== id)
    setCart(newCart);
  }

  function changeQuantity(event, id) { // function run when I update the dropdown on an item
    let newCart = [...cart];
    for (let i=0; i<cart.length; i++) {
      if (cart[i].id === id) {
        newCart[i] = {
          ...newCart[i],
          quantity: parseInt(event.target.value),
        }
      }
    }
    setCart(newCart);
  }

  return (
    <div className='px-3 text-gray-800'>
      <h1 className='my-10 text-2xl font-bold'>Shopping Cart</h1>
      <div className='grid grid-cols-10'>
        <div className='col-span-5 flex flex-col mb-5 border-b text-gray-800'>
          {cart.length === 0 ? <p>You have no items in your cart. <a href="/shop" className='text-indigo-600'>Go shopping</a> to add some!</p> : ""}
          {cart.map((value, index, array) => {
            return(<CartItem value={value} removeItem={removeItem} changeQuantity={changeQuantity} />)
          })} // this works just fine for each item, no matter the action
        </div>
        <div className='col-span-1'></div>
        <CartOrder cart={cart} /> // this is the order summary, only updates appropriately when I remove an item, not when I change the quantity
      </div>
    </div>
  );
};

export default OuterCart;

If necessary, here’s the code for the Order Summary component:

import { React } from 'react';

const CartOrder = ({cart}) => {
  const subtotal = cart.reduce((sum, item) => sum + item.price, 0);

  const taxEstimate = parseFloat((subtotal * .06).toFixed(2));
  const taxEstimateString = parseFloat(subtotal * .06).toFixed(2);

  const orderTotalString = parseFloat(subtotal + taxEstimate).toFixed(2);
  const orderTotal = parseFloat((subtotal + taxEstimate).toFixed(2));

  return (
    <div className='col-span-4 text-gray-800'>
      <div className='rounded-xl bg-gray-100 px-7 py-10'>
        <h1 className='text-lg font-medium mb-4'>Order summary</h1>

        <div className='flex justify-between border-b py-4'>
          <p className='text-gray-500 text-sm'>Subtotal</p>
          <p className='font-medium text-sm'>${subtotal}</p>
        </div>
        <div className='flex justify-between border-b py-4'>
          <p className='text-gray-500 text-sm'>Tax estimate</p>
          <p className='font-medium text-sm'>${taxEstimateString}</p>
        </div>
        <div className='flex justify-between py-4'>
          <p className='font-semibold'>Order total</p>
          <p className='font-semibold'>${orderTotalString}</p>
        </div>
        
        <a href='/' className='mt-5 inline-block w-full bg-indigo-600 hover:bg-indigo-700 transition text-gray-50 text-center px-3 py-3 font-medium tracking-wide rounded-lg'>Checkout</a>
      </div>
    </div>
  );
};

export default CartOrder;

I hate to ask two related questions in such quick succession, but I’ve been stuck on this problem for a good hour now. Any help is appreciated.

>Solution :

In CartOrder function, you aren’t taking account of the quantity of the items.

It should be =>

  const subtotal = cart.reduce((sum, item) => sum + item.price*item.quantity, 0);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading