Home > Enterprise >  My function will loop through an older state just after the state is updated
My function will loop through an older state just after the state is updated

Time:07-10

In this project I'm attempting to make a simple Online Shop using React JS. The issue I'm having involves setState and lifecycle. Whenever an item in added to a cart its put into an array of objects. The user can also add more then one of the same item to their shopping cart.

The issue I'm having involves calculating the price of an item. Whenever the user put's an item into their cart the price calculates to 0, but when they add another item the price adds up to having two items.

User adds One $3.00 item the total price comes up to $0.00

User adds Two $3.00 items the total price comes up to $6.00

I can't seem to figure out why it's behaving this way.

Disclaimer. This project is not going to be deployed. This project was created to utilize my skills I've already picked up.

import React from 'react'

import StoreSelection from './StoreSelection';


const Store = ({inventory,cart,setCart,setPrice}) => {
  const cart_addItem = (newItem) =>{

    let duplicate = false;
    let indextochange = 0;

    for(let item in cart){
      if(cart[item].id === newItem.id){
        duplicate = true;
        indextochange = item;
      }
    }
    
    if(duplicate===true){
      let newList = [];
      for(let item in cart){
        newList[item] = cart[item];
      }
      newList[indextochange].quantity  =1;
      setCart(newList);
    }else{
      newItem.quantity = 1;
      setCart([...cart,newItem]);
    }
    calculatePrice(cart);
  }

  const calculatePrice = (list) =>{
    let newprice = 0;
    console.log(list);
    for(let item in list){
      console.log(list[item].quantity);
      newprice = (parseFloat(list[item].price) * list[item].quantity)   newprice;
    }
    setPrice(newprice);
  }
  
  return (
    <div>
      <StoreSelection inventory={inventory} cart_addItem={cart_addItem}/>
    </div>
  )
}

export default Store

CodePudding user response:

I left inline comments in the refactored code below. If something is unclear, feel free to ask for clarification in a comment to this answer.

Reference documentation for the hooks used:

import {default as React, useCallback, useEffect} from 'react';
import StoreSelection from './StoreSelection';

// This doesn't need to be created in your component.
// Creating it once, outside the component, is an optimization:
function calculatePrice (cart) {
  let updatedPrice = 0;
  // console.log(list);
  for (const item of cart){
    // console.log(item.quantity);
    updatedPrice  = parseFloat(item.price) * item.quantity;
  }
  return updatedPrice;
}

export default function Store ({cart, inventory, setCart, setPrice}) {
  // You can calculate the new price every time the cart changes by updating it
  // in response to changes in the cart state:
  useEffect(() => setPrice(calculatePrice(cart)), [cart]);
  // However, if you don't manually update the price state in other places,
  // then it doesn't need to be state at all. You can just create it this way
  // in the parent component where it was defined:
  // const price = useMemo(() => calculatePrice(cart), [cart]);

  const cart_addItem = useCallback(item => {
    // In your question's code it appears as though it is not certain that
    // the added item's `quantity` property is set. If that's not the case,
    // then you can simply delete the following statement. If it is
    // `undefined` or `null`, then this will set it to `1`:
    item.quantity ??= 1;

    // Use the functional form of the argument to `setCart`. This way,
    // it will not depend on an external state value (so it will
    // always be current and also won't be needed in the dependency array):
    setCart(cart => {
      const index = cart.findIndex(currentItem => currentItem.id === item.id);
      const updatedCart = [...cart];
      if (index >= 0) {
        // Be sure not to mutate the item object within in the cart state:
        const updatedItem = {...updatedCart[index]};
        updatedItem.quantity  = item.quantity;
        updatedCart[index] = updatedItem;
      }
      else updatedCart.push(item);
      return updatedCart;
    });
  }, [setCart]);
  
  return (
    <div>
      <StoreSelection {...{cart_addItem, inventory}}/>
    </div>
  );
}

  • Related