Loading

Quipoin Menu

Learn • Practice • Grow

react / Ecommerce Cart Project
tutorial

Ecommerce Cart Project

Building an e-commerce shopping cart is a great way to learn more advanced React concepts like context, reducers, and complex state management. In this project, we'll create a simple product listing with add-to-cart functionality and a cart page.

What We're Building

An e-commerce cart system with:
  • Product list (fetch from an API or static data).
  • Add to cart button on each product.
  • Cart page showing items, quantities, and total price.
  • Ability to increase/decrease quantity or remove items.
  • Cart state managed via Context + useReducer.

A shopping cart project brings together many concepts: context for global state, reducers for complex updates, and real-world UI patterns.

Step 1: Setup
npx create-react-app ecommerce-cart
cd ecommerce-cart
npm start

Step 2: Create Cart Context and Reducer
<!-- context/CartContext.js -->
import React, { createContext, useReducer, useContext } from 'react';

const CartContext = createContext();

const initialState = { cartItems: [] };

function cartReducer(state, action) {
  switch (action.type) {
    case 'ADD_ITEM': {
      const existingItem = state.cartItems.find(item => item.id === action.payload.id);
      if (existingItem) {
        return {
          ...state,
          cartItems: state.cartItems.map(item =>
            item.id === action.payload.id
              ? { ...item, quantity: item.quantity + 1 }
              : item
          )
        };
      }
      return {
        ...state,
        cartItems: [...state.cartItems, { ...action.payload, quantity: 1 }]
      };
    }
    case 'REMOVE_ITEM':
      return {
        ...state,
        cartItems: state.cartItems.filter(item => item.id !== action.payload.id)
      };
    case 'UPDATE_QUANTITY':
      return {
        ...state,
        cartItems: state.cartItems.map(item =>
          item.id === action.payload.id
            ? { ...item, quantity: action.payload.quantity }
            : item
        )
      };
    default:
      return state;
  }
}

export function CartProvider({ children }) {
  const [state, dispatch] = useReducer(cartReducer, initialState);

  return (
    <CartContext.Provider value={{ state, dispatch }}>
      {children}
    </CartContext.Provider>
  );
}

export function useCart() {
  return useContext(CartContext);
}

Step 3: Product Data (static or API)
<!-- data/products.js -->
export const products = [
  { id: 1, name: 'Laptop', price: 999 },
  { id: 2, name: 'Mouse', price: 25 },
  { id: 3, name: 'Keyboard', price: 75 },
  { id: 4, name: 'Monitor', price: 299 }
];

Step 4: ProductList Component
import React from 'react';
import { useCart } from '../context/CartContext';
import { products } from '../data/products';

function ProductList() {
  const { dispatch } = useCart();

  const addToCart = (product) => {
    dispatch({ type: 'ADD_ITEM', payload: product });
  };

  return (
    <div>
      <h2>Products</h2>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '1rem' }}>
        {products.map(product => (
          <div key={product.id} style={{ border: '1px solid #ccc', padding: '1rem' }}>
            <h3>{product.name}</h3>
            <p>${product.price}</p>
            <button onClick={() => addToCart(product)}>Add to Cart</button>
          </div>
        ))}
      </div>
    </div>
  );
}

export default ProductList;

Step 5: Cart Component
import React from 'react';
import { useCart } from '../context/CartContext';

function Cart() {
  const { state, dispatch } = useCart();
  const { cartItems } = state;

  const total = cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0);

  return (
    <div>
      <h2>Shopping Cart</h2>
      {cartItems.length === 0 ? (
        <p>Your cart is empty.</p>
      ) : (
        <>
          {cartItems.map(item => (
            <div key={item.id} style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
              <span>{item.name} - ${item.price} x {item.quantity}</span>
              <div>
                <button
                  onClick={() => dispatch({ type: 'UPDATE_QUANTITY', payload: { id: item.id, quantity: item.quantity + 1 } })}
                >+</button>
                <button
                  onClick={() => dispatch({ type: 'UPDATE_QUANTITY', payload: { id: item.id, quantity: Math.max(1, item.quantity - 1) } })}
                >-</button>
                <button onClick={() => dispatch({ type: 'REMOVE_ITEM', payload: { id: item.id } })}>Remove</button>
              </div>
            </div>
          ))}
          <h3>Total: ${total}</h3>
        </>
      )}
    </div>
  );
}

export default Cart;

Step 6: Bring It All Together in App
import React from 'react';
import { CartProvider } from './context/CartContext';
import ProductList from './components/ProductList';
import Cart from './components/Cart';

function App() {
  return (
    <CartProvider>
      <div>
        <ProductList />
        <hr />
        <Cart />
      </div>
    </CartProvider>
  );
}

export default App;

Two Minute Drill

  • E-commerce cart project teaches global state management with Context and useReducer.
  • Use `useReducer` for complex state updates (adding, removing, updating quantities).
  • Provide cart state via Context to any component that needs it.
  • Compute totals dynamically based on cart items.
  • This pattern scales well for real e-commerce applications.

Need more clarification?

Drop us an email at career@quipoinfotech.com