'React - context not updating correctly

I have the following component which is being used in a SweetAlert popup:

import React, {useContext, useState} from "react";
import {CartContext} from "../../../context/CartContext";

import styles from './ShoppingCartQuantity.module.css'

export const withShoppingCartContext = Component => props => {
    const { cart, removeItem, updateCart } = useContext(CartContext);
    return <Component {...props} {...{ cart, removeItem, updateCart }} />;
}

const ShoppingCartQuantity = ({ qty, productId, updateCart }) => {
    const [quantity, setQuantity] = useState(qty);

    const updateCartHandler = (productId, amount) => {
        setQuantity(Math.max(quantity + amount, 1));
        updateCart(productId, amount);
    }

    return (
        <div>
            <span>
                <span
                    className={`${styles.op} ${styles.decrementBtn}`}
                    onClick={() => updateCartHandler(productId, -1)}
                >
                  -
                </span>
                <span className={styles.qty}>{quantity}</span>
                <span
                    className={`${styles.op} ${styles.incrementBtn}`}
                    onClick={() => updateCartHandler(productId, 1)}
                >
                  +
                </span>
            </span>
        </div>
    )
}

export default ShoppingCartQuantity;

Here's a visual of the component: enter image description here

I am using this component to update this context:

import React, {createContext, useEffect, useState} from "react";

export const CartContext = createContext();

const CartContextProvider = (props) => {
    const [cart, setCart] = useState(JSON.parse(localStorage.getItem('cart')) || []);

    useEffect(() => {
        localStorage.setItem('cart', JSON.stringify(cart));
        console.log(cart);
    }, [cart]);

    const updateCart = (productId, amount) => {
        if (cart.some(item => item.id === productId)) {
            setCart(cart => cart.map(item => item.id === productId
                ? {
                    ...item,
                    qty: Math.max(item.qty + amount, 1),
                }
                : item
            ));
        } else {
            const item = {
                id: productId,
                qty: 1              
            }

            const updatedCart = [...cart, item];
            setCart(updatedCart);
        }
        console.log(cart);
    }

    const removeItem = (id) => {
        setCart(cart.filter(item => item.id !== id));
    };

    return (
        <CartContext.Provider value={{cart, updateCart, removeItem}}>
            {props.children}
        </CartContext.Provider>
    )
};

export default CartContextProvider;

When I open the popup for the first time the initial value is 0 and when I click the increment button, no matter how many times I click it, the 2 console.log give me the following results:

enter image description here

So in the updateCart function, cart is always empty and in useEffect the cart has the required id but not the required qty as it should have been 4 since I clicked 4 times on the increment button.

Now If I close the popup and open it again, it displays the quantity 1(not 4) as this is the current state. If I start to increment(let's say 4 times) again, this is the result of the console.logs:

enter image description here

Now the useEffect gets the correct qty.

So, from what I understood, if an id is not in the cart array initially, no matter how much I increment it will always be added with qty 1 but if the id is already in the array, the increment works correctly.

What can I do to solve this issue?



Solution 1:[1]

the problem is coming from your updateCart Funtion

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Frankelly