Reputation: 401
I know this is a common issue due to asynchronous nature of react hook updates, and I saw there are a few similar questions already. However I can't figure out how to make this work.
I have an empty array of objects (a shopping cart) that, when addToCart is clicked on a specific product, needs to create a new object with all the data about that product. The first time I click, I only get an empty object. From the second time everything seems to work.
Array:
const [cartArray, setCartArray] = useState([
{ imgUrl: "", nameUrl: "", priceUrl: "", id: "" },
]);
Then it's passed as a prop here, where there is the addToCart function and the click events that triggers it:
const Product = ({
imgUrl,
nameUrl,
priceUrl,
id,
description,
cartArray,
setCartArray,
productArray,
}) => {
const [title, setTitle] = useState("");
const [productId, setProductId] = useState("");
const [price, setPrice] = useState("");
const [img, setImg] = useState("");
const [modalClassName, setModalClassName] = useState("hidden");
const addToCart = () => {
setCartArray((prev) => [
{
imgUrl: imgUrl,
nameUrl: nameUrl,
priceUrl: priceUrl,
id: id,
},
...prev,
]);
};
return (
<div className="product">
<div className="img-container">
<img src={imgUrl} alt="product image" />
</div>
<div className="product-description">
<p>{nameUrl}</p>
<h3>€ {priceUrl}</h3>
</div>
<div className="button-container">
<AddShoppingCartIcon
className="btn btn-add-to-cart"
onClick={addToCart}
/>
<FavoriteBorderIcon className="btn btn-favorite" />
</div>
</div>
);
};
And here's where the Product component is rendered:
const ProductContainer = ({
productArray,
setProductArray,
showNavBar,
cartArray,
setCartArray,
}) => {
useEffect(() => {
axios
.get("https://fakestoreapi.com/products")
.then((res) => setProductArray(res.data));
console.log(productArray);
}, []);
return (
<div className="product-container-parent" id="shop" onScroll={showNavBar}>
<div className="product-container-header">
<h1>New Arrivals</h1>
</div>
<div className="product-container">
{productArray.map((e) => {
return (
<Product
imgUrl={e.image}
nameUrl={e.title}
priceUrl={e.price}
id={e.id}
description={e.description}
cartArray={cartArray}
setCartArray={setCartArray}
productArray={productArray}
/>
);
})}
</div>
</div>
);
};
Any ideas? Thank you!
Upvotes: 1
Views: 164
Reputation: 36
The initial state for cartArray
seems to be having an empty obj { imgUrl: "", nameUrl: "", priceUrl: "", id: "" }
The addToCart
function appends the new object to the cartArray
. So you'll get the empty object as the first one rendered. I would suggest to set initial state for cartArray
as empty array.
const [cartArray, setCartArray] = useState([]);
Upvotes: 1