I am proud of learning how to create & use React Context & Provider:
interface CartContextType { products: Product[]; cart: CartItemType[]; addToCart: (product: Product) => void; removeFromCart: (productId: number) => void; emptyCart: () => void; findCartItem: (productId: number) => CartItemType | undefined; reduceQty: (product: Product) => void; increaseQty: (product: Product) => void; getTotalCost: () => number; isModalOpen: boolean; openModal: () => void; closeModal: () => void; resetCart: () => void; } export const CartContext = createContext<CartContextType | undefined>( undefined, ); export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children, }) => { const { products } = useFetchProducts(); const [cart, setCart] = useState<CartItemType[]>([]); const [isModalOpen, setIsModalOpen] = useState(false); const openModal = useCallback(() => setIsModalOpen(true), []); const closeModal = useCallback(() => setIsModalOpen(false), []); const resetCart = useCallback(() => { setCart([]); closeModal(); }, [closeModal]); const addToCart = useCallback((product: Product) => { setCart((prevCart) => { return [...prevCart, { ...product, quantity: 1 }]; }); }, []); const increaseQty = useCallback((product: Product) => { setCart((prevCart) => { return prevCart.map((item) => item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item, ); }); }, []); const reduceQty = useCallback((product: Product) => { setCart((prevCart) => { const updatedCart = prevCart .map((item) => { if (item.id === product.id) { const qty = item.quantity; if (qty === 1) { return null; } return { ...item, quantity: item.quantity - 1 }; } return item; }) .filter((item): item is CartItemType => item !== null); return updatedCart; }); }, []); const removeFromCart = useCallback((productId: number) => { setCart((prevCart) => prevCart.filter((item) => item.id !== productId)); }, []); const emptyCart = useCallback(() => { setCart([]); }, []); const findCartItem = useCallback( (productId: number) => { return cart.find((item) => item.id === productId); }, [cart], ); const getTotalCost = useCallback(() => { return cart.reduce((acc, item) => acc + item.price * item.quantity, 0); }, [cart]); const contextValue = useMemo( () => ({ products, cart, addToCart, removeFromCart, emptyCart, findCartItem, reduceQty, increaseQty, getTotalCost, isModalOpen, openModal, closeModal, resetCart, }), [ products, cart, addToCart, removeFromCart, emptyCart, findCartItem, reduceQty, increaseQty, getTotalCost, isModalOpen, openModal, closeModal, resetCart, ], ); return ( <CartContext.Provider value={contextValue}>{children}</CartContext.Provider> ); };
export const useCart = () => { const context = useContext(CartContext); if (!context) { throw new Error("useCart must be used within a CartProvider"); } return context; };
What specific areas of your project would you like help with?function App() { return ( <ThemeProvider theme={theme}> <CartProvider> <GlobalStyles /> <Container> <ProductList /> <Cart /> </Container> <OrderDialog /> </CartProvider> </ThemeProvider> ); }
I still struggle with positioning certain UI elements. Like The "Add to Cart Button" in this challenge. Any tips or resources for learning that would be great!