Skip to main content

Overview

The useCartStore is a Zustand store that manages the shopping cart state across the application. It provides methods to add, remove, update quantities, and clear the cart. The store uses Zustand’s persist middleware to save cart data to local storage under the key cart-storage. Store Location: src/store/useCartStore.js

State Shape

cart
array
required
Array of cart items. Each item contains the product data plus a qty field.

Methods

addToCart

Adds a product to the cart. If the product already exists, increments the quantity by 1. Otherwise, adds it with qty: 1.
product
object
required
The product object to add to the cart. Must include id, title, price, and thumbnail fields.
const addToCart = useCartStore((state) => state.addToCart);

addToCart({
  id: 1,
  title: "Premium Headphones",
  price: 99.99,
  thumbnail: "/images/headphones.jpg"
});

increaseQty

Increases the quantity of a cart item by 1.
id
string | number
required
The product ID to increase quantity for
const increaseQty = useCartStore((state) => state.increaseQty);

increaseQty(1);

decreaseQty

Decreases the quantity of a cart item by 1. If quantity reaches 0, the item is automatically removed from the cart.
id
string | number
required
The product ID to decrease quantity for
const decreaseQty = useCartStore((state) => state.decreaseQty);

decreaseQty(1);

removeFromCart

Removes an item from the cart completely, regardless of quantity.
id
string | number
required
The product ID to remove from the cart
const removeFromCart = useCartStore((state) => state.removeFromCart);

removeFromCart(1);

clearCart

Clears all items from the cart.
const clearCart = useCartStore((state) => state.clearCart);

clearCart();

Usage Examples

Basic Usage - Single Selector

import { useCartStore } from "../../store/useCartStore";

export const Cart = () => {
  const { cart, increaseQty, decreaseQty, removeFromCart } = useCartStore();

  const total = cart.reduce((acc, item) => acc + item.price * item.qty, 0);
  const totalItems = cart.reduce((acc, item) => acc + item.qty, 0);

  return (
    <div>
      <h2>Shopping Cart ({totalItems} items)</h2>
      {cart.map((item) => (
        <div key={item.id}>
          <h3>{item.title}</h3>
          <p>${(item.price * item.qty).toFixed(2)}</p>
          <div>
            <button onClick={() => decreaseQty(item.id)}>-</button>
            <span>{item.qty}</span>
            <button onClick={() => increaseQty(item.id)}>+</button>
          </div>
          <button onClick={() => removeFromCart(item.id)}>Remove</button>
        </div>
      ))}
      <h3>Total: ${total.toFixed(2)}</h3>
    </div>
  );
};

Checkout Flow

import { useCartStore } from "../../store/useCartStore";
import { useUserStore } from "../../store/useUserStore";
import { useNavigate } from "react-router-dom";

export const CheckoutPayment = () => {
  const cart = useCartStore((state) => state.cart);
  const clearCart = useCartStore((state) => state.clearCart);
  const addOrder = useUserStore((state) => state.addOrder);
  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    
    const order = {
      id: Date.now(),
      items: cart,
      total: cart.reduce((acc, item) => acc + item.price * item.qty, 0),
      date: new Date().toISOString()
    };
    
    addOrder(order);
    clearCart();
    navigate("/order-confirmation");
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Payment form fields */}
      <button type="submit">Place Order</button>
    </form>
  );
};

Local Storage

The cart store is persisted to local storage with the key cart-storage. This allows the cart to persist across browser sessions and page refreshes.

Storage Structure

{
  "state": {
    "cart": [
      {
        "id": 1,
        "title": "Premium Headphones",
        "price": 99.99,
        "thumbnail": "/images/headphones.jpg",
        "qty": 2
      }
    ]
  },
  "version": 0
}

Best Practices

  1. Selector Optimization: Use specific selectors to avoid unnecessary re-renders
    // Good - only re-renders when cart changes
    const cart = useCartStore((state) => state.cart);
    
    // Good - only re-renders when needed method is added/changed
    const addToCart = useCartStore((state) => state.addToCart);
    
    // Avoid - re-renders on any state change
    const store = useCartStore();
    
  2. Computed Values: Calculate totals in components rather than storing them
    const total = cart.reduce((acc, item) => acc + item.price * item.qty, 0);
    const totalItems = cart.reduce((acc, item) => acc + item.qty, 0);
    
  3. Type Safety: Consider adding TypeScript types for better development experience
    interface CartItem {
      id: number;
      title: string;
      price: number;
      thumbnail: string;
      qty: number;
    }
    

Build docs developers (and LLMs) love