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-cartcd ecommerce-cartnpm startStep 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
