Skip to content

Instantly share code, notes, and snippets.

@edoves
Created October 30, 2024 14:45
Show Gist options
  • Save edoves/4d559851e5c45abc7d03f71ae0414ffc to your computer and use it in GitHub Desktop.
Save edoves/4d559851e5c45abc7d03f71ae0414ffc to your computer and use it in GitHub Desktop.
Context API setup with Typescript

Context API setup with Typescript

Step 1: Define Types

First, define the interfaces for your products and cart items. Create a file types.ts for these definitions: types.ts

export Type Product {
  id: number;
  name: string;
  price: number;
  description: string;
  imageUrl: string;
}

export Type CartItem {
  productId: number;
  quantity: number;
}

Step 2: Create the Context

Create the context and provide default values. Create a file context.tsx for this: context.tsx

import React, { createContext, useState, ReactNode } from 'react';
import { Product, CartItem } from './types';

interface AppContextProps {
  products: Product[];
  cartItems: CartItem[];
  addProduct: (product: Product) => void;
  addToCart: (productId: number) => void;
  removeFromCart: (productId: number) => void;
  clearCart: () => void;
}

const defaultContext: AppContextProps = {
  products: [],
  cartItems: [],
  addProduct: () => {},
  addToCart: () => {},
  removeFromCart: () => {},
  clearCart: () => {},
};

export const AppContext = createContext<AppContextProps>(defaultContext);

export const AppProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [products, setProducts] = useState<Product[]>([]);
  const [cartItems, setCartItems] = useState<CartItem[]>([]);

  const addProduct = (product: Product) => {
    setProducts((prevProducts) => [...prevProducts, product]);
  };

  const addToCart = (productId: number) => {
    setCartItems((prevCartItems) => {
      const item = prevCartItems.find((item) => item.productId === productId);
      if (item) {
        return prevCartItems.map((item) =>
          item.productId === productId ? { ...item, quantity: item.quantity + 1 } : item
        );
      } else {
        return [...prevCartItems, { productId, quantity: 1 }];
      }
    });
  };

  const removeFromCart = (productId: number) => {
    setCartItems((prevCartItems) =>
      prevCartItems.filter((item) => item.productId !== productId)
    );
  };

  const clearCart = () => {
    setCartItems([]);
  };

  return (
    <AppContext.Provider
      value={{ products, cartItems, addProduct, addToCart, removeFromCart, clearCart }}
    >
      {children}
    </AppContext.Provider>
  );
};

Step 3: Provide the Context

Wrap your application with the AppProvider in index.tsx or App.tsx:

// index.tsx or App.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import { AppProvider } from './context';
import App from './App';

ReactDOM.render(
  <AppProvider>
    <App />
  </AppProvider>,
  document.getElementById('root')
);

Step 4: Consume the Context

Use the context in your components using the useContext hook:

// SomeComponent.tsx

import React, { useContext } from 'react';
import { AppContext } from './context';

const SomeComponent: React.FC = () => {
  const { products, cartItems, addProduct, addToCart, removeFromCart, clearCart } = useContext(AppContext);

  // Example usage
  const handleAddProduct = () => {
    const newProduct = { id: 1, name: 'Example Product', price: 100, description: 'This is an example product', imageUrl: 'example.jpg' };
    addProduct(newProduct);
  };

  const handleAddToCart = (productId: number) => {
    addToCart(productId);
  };

  return (
    <div>
      <h1>Products</h1>
      {products.map((product) => (
        <div key={product.id}>
          <h2>{product.name}</h2>
          <button onClick={() => handleAddToCart(product.id)}>Add to Cart</button>
        </div>
      ))}

      <h1>Cart</h1>
      {cartItems.map((item) => (
        <div key={item.productId}>
          <p>Product ID: {item.productId}</p>
          <p>Quantity: {item.quantity}</p>
          <button onClick={() => removeFromCart(item.productId)}>Remove</button>
        </div>
      ))}

      <button onClick={clearCart}>Clear Cart</button>
    </div>
  );
};

export default SomeComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment