Project Idea: E-commerce Cart

This project is essential for every React developer's portfolio. We will build a professional-looking product page. When a user clicks 'Add to Cart', the item will be added to a global cart state. The user can then navigate to the `/cart` page to see all their items. The main focus is Global State Management using the Context API to avoid "prop drilling".

✨ Key Features

  • A product page showing item details.
  • "Add to Cart" button to add items to a global cart.
  • A separate "Cart" page (`/cart`) to display all selected items.
  • Ability to see the total number of items in the cart (e.g., in the navbar).
  • A global state that is accessible from any component.

💻 Tech Stack & Skills

  • Tech Stack: React, React Router, Context API, `useReducer` hook.
  • Skills Practiced: Global State Management, `useContext` hook, `useReducer` hook, avoiding prop-drilling, React Router for navigation, managing complex app-wide state.
React React
React Router React Router
Context API Context API

🛠️ Full Step-by-Step Tutorial

Let's build this. This tutorial assumes you have a React app set up with `react-router-dom` installed (`npm i react-router-dom`).

Step 1: File Structure

In your src folder, create a structure like this:

/src
  /components
    - Navbar.js
    - ProductList.js
    - CartPage.js
  /context
    - CartContext.js
  - App.js
  - index.js
  - style.css (Your main CSS)

Step 2: Create the Cart Context (`CartContext.js`)

This is the heart of our app. We'll use `useReducer` because it's better for managing complex state (like a cart) than `useState`.

src/context/CartContext.js
import React, { createContext, useContext, useReducer } from 'react';

// 1. Define the initial state
const initialState = {
    items: [],
};

// 2. Create the reducer function
const cartReducer = (state, action) => {
    switch (action.type) {
        case 'ADD_TO_CART':
            // (Add logic to handle duplicates if you want)
            return {
                ...state,
                items: [...state.items, action.payload],
            };
        case 'REMOVE_FROM_CART':
            return {
                ...state,
                items: state.items.filter(item => item.id !== action.payload.id),
            };
        default:
            return state;
    }
};

// 3. Create the Context
export const CartContext = createContext();

// 4. Create the Provider Component
export const CartProvider = ({ children }) => {
    const [state, dispatch] = useReducer(cartReducer, initialState);

    return (
        
            {children}
        
    );
};

// 5. Create a custom hook for easy access
export const useCart = () => {
    return useContext(CartContext);
};

Step 3: Wrap Your App (`index.js`)

Now we must "provide" this context to our entire app.

src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { CartProvider } from './context/CartContext';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  
    
      
        
      
    
  
);

Step 4: Setup Routing (`App.js`)

Let's set up the pages for our app.

src/App.js
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Navbar from './components/Navbar';
import ProductList from './components/ProductList';
import CartPage from './components/CartPage';
import './style.css'; // Assuming you have main styles

function App() {
  return (
    
} /> } />
); } export default App;

Step 5: Create the `ProductList.js` Component

This component will show our products and let users add them to the cart.

src/components/ProductList.js
import React from 'react';
import { useCart } from '../context/CartContext';

// Dummy product data
const dummyProducts = [
    { id: 1, name: 'React T-Shirt', price: 25 },
    { id: 2, name: 'Node.js Hoodie', price: 45 },
    { id: 3, name: 'JavaScript Mug', price: 15 },
];

function ProductList() {
    // Get the dispatch function from our context
    const { dispatch } = useCart();

    const handleAddToCart = (product) => {
        dispatch({
            type: 'ADD_TO_CART',
            payload: product,
        });
    };

    return (
        

Products

{dummyProducts.map(product => (

{product.name}

${product.price}

))}
); } export default ProductList;

Step 6: Create the `CartPage.js` Component

This page will show items in the cart and let users remove them.

src/components/CartPage.js
import React from 'react';
import { useCart } from '../context/CartContext';

function CartPage() {
    // Get both state and dispatch from our context
    const { state, dispatch } = useCart();

    const handleRemove = (item) => {
        dispatch({
            type: 'REMOVE_FROM_CART',
            payload: item,
        });
    };

    const totalPrice = state.items.reduce((total, item) => total + item.price, 0);

    return (
        

My Cart

{state.items.length === 0 ? (

Your cart is empty.

) : (
{state.items.map(item => (
{item.name} - ${item.price}
))}

Total: ${totalPrice}

)}
); } export default CartPage;

Step 7: Update the `Navbar.js` Component

Finally, let's show the cart count in the navbar.

src/components/Navbar.js
import React from 'react';
import { Link } from 'react-router-dom';
import { useCart } from '../context/CartContext';

function Navbar() {
    // Get the cart state
    const { state } = useCart();
    const cartCount = state.items.length;

    return (
        
); } export default Navbar;

Aur yeh ho gaya! Ab aapke paas ek fully functional cart system hai jo poori app mein kahin se bhi access ho sakta hai.

🔥 Next Steps & Challenges

After completing this tutorial, try these ideas:

  • **Handle Quantity:** Abhi humara cart sirf item add karta hai. Logic update karein taaki agar item pehle se cart mein hai, toh uski quantity badhe.
  • **Local Storage:** Cart items ko `localStorage` mein save karein taaki page reload hone par bhi cart khali na ho.
  • **Backend:** Ek fake API (like `fakestoreapi.com`) se products fetch karein instead of using dummy data.