简体   繁体   中英

How should i create logic for checkout page for an e-commerce website?

I am using React and building a simple e-commerce project. On the shop page, when I click a product's "+" button, that product will be added to the checkout items. The issue is that if you add more than one of the same product, it will add it as another item. What I want to do is if a product's quantity is greater than 1, then just show 1 item and show the quantity.

I use useContext for share all data to shop and checkout pages. I created the addItem function and all states in that context.(ShopContext)

ShopContext

 const [products, setProducts] = useState([]);
 const [checkoutItems, setCheckoutItems] = useState([]);

const addItem = (id) => {
    const newProduct = id;
    setCheckoutItems([...checkoutItems, products[newProduct]]);
  };

 const values = {
    products,
    addItem,
    checkoutItems,
  };
  return (
    <ShopContext.Provider value={values}>{props.children}</ShopContext.Provider>
  );

The button:

<button
              id={idx}
              className="bg-purple-400 px-4"
              onClick={(e) => addItem(e.target.id)}>+</button>

Checkout Page

const Checkout = () => {
  const { checkoutItems } = useContext(ShopContext);
  return (
    <div className="my-7 lg:max-w-7xl mx-auto font-Rubik items-center">
      {JSON.stringify(checkoutItems)}
    </div>
  );
};

Your checkoutItems should be an array of objects with properties like

[ { id: 'abc', quantity: 2 }, { id: 'cde', quantity: 1 ] 

On backend you should retrieve the price of the product base on ID and display it to the user. You don't need more information (such as price etc.) in your frontend because all of this should be handled by backend. You also don't want to have any endpoint on your server which will allow information such as price to be sent by frontend.

One way to solve this issue is to keep track of the quantity of each item in the checkoutItems state. You can do this by creating an object for each item that includes the product information as well as a quantity property.

In the addItem function, you can check if the item already exists in the checkoutItems state. If it does, you can increment the quantity property. If it doesn't, you can add a new object to the state with the product information and a quantity of 1.

Here's an example of how you can update your code:

ShopContext

const addItem = (id) => {
const newProduct = products[id];
const existingItem = 
checkoutItems.find(item => item.id === id);
if(existingItem){
setCheckoutItems(checkoutItems.map(item => item.id === id ? {...item, quantity: item.quantity+1} : item));
} else {
setCheckoutItems([...checkoutItems, {...newProduct, quantity: 1}]);
}
};

CheckoutPage

const Checkout = () => {
const { checkoutItems } = 
useContext(ShopContext);
return (
<div className="my-7 lg:max-w-7xl mx-auto font-Rubik items-center">
{checkoutItems.map(item => <div> 
{item.name} - Quantity: {item.quantity} 
</div>)}
</div>
);
};

You can then use the quantity property to display the correct quantity on the checkout page.

Apologies for the code, I'm on my mobile

The issue with your current code is that you are adding a new object to the checkoutItems state each time the "+" button is clicked, instead of updating the quantity of an existing item. To fix this, you need to check if the item already exists in the checkoutItems state, and if it does, you should update the quantity property of that item.

To accomplish this, you can use the Array.prototype.find() method to find the existing item in the checkoutItems state, and then use the Array.prototype.map() method to update the quantity property of that item.

Regarding the newProduct = products[id], it is used to get the product object from the products state by its id, so that you can add it to the checkoutItems state.

Also, you are using JSON.stringify on checkoutItems in Checkout component, and it will not display the item's name and quantity. You should use map to iterate and display the item's name and quantity.

The reason find() method is returning undefined is because it's not able to find the matching item in the checkoutItems state. This could be due to the fact that the id's of the products in the products state and the checkoutItems state are not the same.

Using the array indexer like checkoutItems[0].id === id would only check the first item in the checkoutItems state and will not check other items.

You can use the Array.prototype.filter() method to iterate through the checkoutItems state, and check for the existence of the item in the state by its id.

Here's an example of how you can update your code:

const addItem = (id) => {
const newProduct = products.find(product => product.id === id);
const existingItem = checkoutItems.filter(item => item.id === id);
if (existingItem.length > 0) {
setCheckoutItems(
  checkoutItems.map(item =>
    item.id === id ? { ...item, quantity: item.quantity + 1 } : item
  )
);
 } else {
setCheckoutItems([...checkoutItems, { ...newProduct, quantity: 1 }]);
}
};

Here I am using the Array.prototype.filter() method to filter the checkoutItems state and check if the item with the given id already exists in the state. If it does, then I am updating the quantity property using the Array.prototype.map() method. If it doesn't, then I am adding the new product to the state with a quantity of 1.

Also, make sure that the id's of the products in the products state and the checkoutItems state are the same, so that you can find and match the items correctly.

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