skip to Main Content

CartPage.jsx

 const [cart, setCart, cartTotal] = useCart()

return (
        {cart?.map((p) => (
                            <div className="item" key={p._id}>
                                <div className="item-product">
                                    <img src={`http://localhost:4000/api/product/photo/${p._id}`}
                                    alt={p.name} width={"200px"} height={"200px"} />
                                    <div className="item-detail">
                                        <h4>{p.name} x {p.quantity}</h4>
                                        <p>{p.description}</p>
                                        <h4>Price: ${p.price}</h4>
                                        <div className="qtyBtns">
                                            <button className='increaseQtyBtn'
                                            onClick={() => {
                                                setCart(
                                                    cart.map((c) => {
                                                        if(c._id === p._id){
                                                            return {...c, quantity: c.quantity++}
                                                        }
                                                    }) 
                                                )
                                                localStorage.setItem(
                                                    "cart",
                                                    JSON.stringify([...cart ])
                                                )
                                            }}>
                                                +
                                            </button>
                                            <button className='decreaseQtyBtn' 
                                            onClick={() => {
                                                setCart(
                                                    cart.map((c) => {
                                                        if(c._id === p._id){
                                                            if(c.quantity === 1){
                                                                setCart(
                                                                    cart.filter((c) => c._id !== p._id)
                                                                )
                                                            } else{
                                                                return {...c, quantity: c.quantity--}
                                                            }
                                                        }
                                                    }) 
                                                )
                                                localStorage.setItem(
                                                    "cart",
                                                    JSON.stringify([...cart ])
                                                )
                                            }}>-</button>
                                        </div>
                                        {/* <h4>Quantity: 1</h4> */}
                                    </div>
                                </div>
                               
                                <button>Remove</button>
                            </div>
                        ))}
)

context/cart.jsx

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

const CartContext = createContext()

const CartProvider = ({ children }) => {
    const [cart,setCart] = useState([])
    const cartTotal = cart.reduce((total, item) => total + item.quantity, 0)
   
    
    useEffect(() => {
        let existingCartItems = localStorage.getItem("cart")
        if(existingCartItems) setCart(JSON.parse(existingCartItems))
    }, [])

    console.log(cartTotal)

    return (
        <CartContext.Provider value={[ cart, setCart, cartTotal ]}>
            {children}
        </CartContext.Provider>
    )
}

const useCart = () => useContext(CartContext)

export { useCart, CartProvider }

Header.jsx

const Header = () => {
    
    const [ cart, setCart, cartTotal ] = useCart()

    return (
 <Badge count={cartTotal} showZero>
                                <NavLink className="link" to="/cart">
                                    Cart
                                </NavLink>
                            </Badge>
)

I am trying to update the quantity value by clicking the buttons + and – but I need to refresh the page at least once in order to have the value in header updating the value of quantity. May I ask any solutions can have the quantity value updated after clicking the buttons without any refresh?

2

Answers


  1. This is a good use case for useSyncExternalStore in React v18. Subscribe to changes in localStorage and return a snapshot when changes happen:

    const cart = useSyncExternalStore(
      function subscribe(callback) {
        window.addEventListener("storage", callback);
        return () => {
          window.removeEventListener("storage", callback);
        };
      },
      function getSnapShot() {
        return localStorage.getItem("cart");
      }
    );
    
    Login or Signup to reply.
  2. You should use prefix increment. This is because when you use postfix increment for {...c, quantity: c.quantity++}, it will return c.quantity in quantity field, then it update c.quantity++. Therefore you see c.quantity only. So you should use {...c, quantity: ++c.quantity} so it can update the c.quantity first then apply to quantity value

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search