I’m trying to make the functionality of adding products to the cart with updating the counter of the number of products and the total amount.
I can’t understand why useEffect is triggered only when a new product is added to the cart. If I update the current quantity of the product that is already in the cart, then useEffect does not work.
const [cart, setCart] = useState([])
const [counter, setCounter] = useState(cart.reduce((prev, curr) => prev + curr.quantity, 0))
const [total, setTotal] = useState(cart.reduce((prev, curr) => prev + curr.price, 0))
const addItemToCart = (id, foodName, url, price, quantity) => {
if (cart.find(el => el.id === id)) {
cart.map(el => {
if (id === el.id) {
const price = el.price / el.quantity
el.quantity += 1
el.price = price * el.quantity
}
return setCart(cart) // useEffect does not work
})
} else {
setCart(() => [...cart, { id, foodName, url, price, quantity }]) // useEffect is triggered
}
}
useEffect(() => {
setCounter(cart.reduce((prev, curr) => prev + curr.quantity, 0))
setTotal(cart.reduce((prev, curr) => prev + curr.price, 0))
}, [cart])
>Solution :
instead of this
return setCart(cart) // useEffect does not work
write
setCart(prevCart => prevCart.map(el => {
if (id === el.id) {
const price = el.price / el.quantity
el.quantity += 1
el.price = price * el.quantity
}
return el
}))
Two issues with your code:
cart.map(el => {
if (id === el.id) {
const price = el.price / el.quantity
el.quantity += 1
el.price = price * el.quantity
}
This doesn’t return anything. Cart.map doesn’t mutate the list. So cart would just be the same I guess the objects would be mutated though, so setCart([...cart]) would work after that.
And
return setCart(cart) // useEffect does not work
setCart can only take a copy of cart. This also wont do anything (see: https://reactjs.org/docs/hooks-state.html)
Fully updated code
const addItemToCart = (id, foodName, url, price, quantity) => {
if (cart.find(el => el.id === id)) {
setCart(prevCart => prevCart.map(el => {
if (id === el.id) {
const price = el.price / el.quantity
el.quantity += 1
el.price = price * el.quantity
}
return el
}))
} else {
setCart(() => [...cart, { id, foodName, url, price, quantity }]) // useEffect is triggered
}
}