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?

1 answer

  • answered 2022-05-04 12:50 Frankelly

    the problem is coming from your updateCart Funtion

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum