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;
}
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>
);
};
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')
);
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;