I'm trying to make simple online shop using React for learning purposes, but I'm having hard time setting quantity of each item as separate value. Right now I have one variable with works for all three items. Here's some code:
- App.js
import { useState } from "react";
import Header from "./Components/Header";
import Cart from "./Components/Cart";
import Shop from "./Components/Shop";
import img1 from "./Pictures/food1.jpg";
import img2 from "./Pictures/food2.jpg";
import img3 from "./Pictures/food3.jpg";
function App() {
const [showCart, setShowCart] = useState(false);
const [items, setItems] = useState([
{
id: 1,
name: "Spaghetti",
price: "300$",
img: img1,
alt: "Plate of Spaghetti",
},
{
id: 2,
name: "Pizza",
price: "500$",
img: img2,
alt: "Pizza",
},
{
id: 3,
name: "Tiramisu",
price: "150$",
img: img3,
alt: "Tiramisu",
},
]);
let [quantity, setQuantity] = useState(0);
const addToCart = () => {
console.log("Add Value");
setQuantity((quantity = 1));
console.log(quantity);
};
const removeFromCart = () => {
console.log("Lower Value");
setQuantity((quantity -= 1));
console.log(quantity);
};
return (
<div className="container">
<Header onShowCart={() => setShowCart(!showCart)} />
{showCart && <Cart items={items} quantity={quantity} />}
<Shop
items={items}
onAdd={addToCart}
onLower={removeFromCart}
quantity={quantity}
/>
</div>
);
}
export default App;
- Shop.js (I'm suspecting that I could somehow create those separate values here using .map()
import Item from "./Item";
const Shop = ({ items, onAdd, onLower, quantity }) => {
return (
<div className="shop">
{items.map((item) => (
<Item
key={item.id}
item={item}
onAdd={onAdd}
onLower={onLower}
quantity={quantity}
/>
))}
</div>
);
};
export default Shop;
- Item.js
import React from "react";
import ItemInfo from "./ItemInfo";
const Item = ({ item, onAdd, onLower, quantity }) => {
return (
<div className="item">
<img className="image" src={item.img} alt={item.alt} />
<ItemInfo
name={item.name}
price={item.price}
onAdd={onAdd}
onLower={onLower}
quantity={quantity}
/>
</div>
);
};
export default Item;
- ItemInfo.js
// import { useState } from "react";
import Button from "./Button";
import ItemNameAndPrice from "./ItemNameAndPrice";
const ItemInfo = ({ name, price, onAdd, onLower, quantity }) => {
return (
<div className="info">
<ItemNameAndPrice name={name} price={price} />
<div id="buttons-box">
<Button text={"-"} onClick={onLower} />
{/* <QuantityOfItems /> */}
<div className="quantity">{quantity}</div>
<Button text={" "} onClick={onAdd} />
</div>
</div>
);
};
export default ItemInfo;
5.ItemNameAndPrice.js
import React from "react";
const ItemNameAndPrice = ({ name, price, quantity }) => {
return (
<div className="name-and-price">
<span id="name">{name}</span>
<span id="price">Price: {price}</span>
<span>{quantity}</span>
</div>
);
};
export default ItemNameAndPrice;
I figured that I could make another component which would store quantity values and operate on them, but in the end I'm remaking the same stuff. Right now this component looks like that:
import { useState } from "react";
const QuantityOfItems = () => {
let [item1Quantity, setItem1Quantity] = useState(0);
let [item2Quantity, setItem2Quantity] = useState(0);
let [item3Quantity, setItem3Quantity] = useState(0);
return <div>{item1Quantity > 0 && item1Quantity}</div>;
};
export default QuantityOfItems;
Nothing important is here at the moment, because like I've said, I'm hitting a wall here.
Here's how the page looks. The quantity value from App.js is being used inside cart too, but It was made for some testing, so don't pay it much attention.
CodePudding user response:
You only have a single quantity
state variable in the App
component. That means there is only 1 value that you are passing down as a prop to the Item
components.
You need to create a separate state variable for each Item
. You could do this by including the quantity
variable as a piece of the Item
's state, like this:
const Item = ({ item, onAdd, onLower }) => {
let [quantity, setQuantity] = useState(0); // <=== quantity state goes inside the item instead of in the props
return (
<div className="item">
<img className="image" src={item.img} alt={item.alt} />
<ItemInfo
name={item.name}
price={item.price}
onAdd={() => {
setQuantity(quantity 1);
}}
onLower={() => {
setQuantity(quantity - 1);
}}
quantity={quantity}
/>
</div>
);
};
You will then need to change your handler functions slightly to use the Item
's setQuantity
rather than the App
's setQuantity
. Note that =
and -=
are not needed.