I’m trying to use the useContext hook in my react app to manage the cart state but I don’t know why am I getting this error again and again that the function that I’m trying to destructure is undefined.
I’m new to using context API please help me with the same. I saw other answers related to context API and tried everything like exporting the CartContext as default and then importing it without destructoring but nothing worked. I’m neither able to import the functions nor the data.
Here is my CartContext.js file
import React, { useState, createContext, useReducer } from "react"; import CartReducer from "./CartReducer"; //Initialized Context export const CartContext = createContext(); export const CartProvider = ({ children }) => { const [products, setProducts] = useState([]); const [state, dispatch] = useReducer(CartReducer, products); function addProductWithQuantity(product) { dispatch({ type: "ADD_PRODUCT", payload: { product, quantity: 1, }, }); } const deleteProductWithId = (id) => { dispatch({ type: "DELETE_PRODUCT", payload: id, }); }; return ( <CartContext.Provider value={{ state, addProductWithQuantity, deleteProductWithId, }} > {children} </CartContext.Provider> ); };
And here is the file where I’m using the useContext.
import React, { useContext } from "react"; import { Card, Typography, Tooltip, IconButton, Button, } from "@material-ui/core"; import { Link } from "react-router-dom"; import styles from "./Product.module.css"; import amazon from "../../icons/amazon-brands.png"; import flipkart from "../../icons/flipkart.png"; import { SnackbarProvider, useSnackbar } from "notistack"; import classNames from "classnames"; import { CartContext } from "../../Context/CartContext"; const Product = ({ product }) => { return ( <SnackbarProvider maxSnack={3} preventDuplicate> <ProductCard product={product} /> </SnackbarProvider> ); }; export default Product; const ProductCard = ({ product }) => { const { id, imageUrls, storeName, category, price, amazonLink, flipkartLink, title, } = product; const iconColor = "var(--primaryColor)"; const { addProductWithQuantity } = useContext(CartContext); //Throws an error always console.log(addProductWithQuantity); const gotoURL = (location) => { let a = document.createElement("a"); a.target = "_blank"; a.href = location; a.click(); }; const handleClickVariant = (variant, title, id) => () => { enqueueSnackbar(`Successfully added ${title} to cart`, { variant, }); onClickHeart(id); // saveToLocal(); addProductWithQuantity(product); }; const saveToLocal = () => { let oldCart = localStorage.getItem("cart"); let newCart = oldCart ? JSON.parse(oldCart) : []; newCart.push(product); localStorage.setItem("cart", JSON.stringify(newCart)); }; const onClickHeart = (id) => { document .getElementById(id) .style.setProperty("color", iconColor, "important"); }; const { enqueueSnackbar } = useSnackbar(); return ( <Card key={id} className={styles.card}> <Link to={`/products/${id.trim()}`} className={styles.noDecoration}> <div className={styles.thumbnail}> <img src={imageUrls[0]} alt={title} /> </div> </Link> <div className={styles.name}> <Typography className={styles.category} variant="subtitle2"> {category} </Typography> <Link to={`/products/${id.trim()}`} className={styles.noDecoration}> <Typography className={styles.company} variant="subtitle1"> {title} </Typography> </Link> </div> <div className={styles.priceLike}> <h4>₹{price}</h4> <Tooltip title="Add to favourites" placement="top"> <IconButton onClick={handleClickVariant("success", title, id)} className={styles.likeIcon} > <i id={id} className={classNames("fas fa-cart-plus")} /> </IconButton> </Tooltip> </div> <div className={styles.buttons}> <Button variant="contained" color="primary" className={styles.amazonBtn} onClick={() => gotoURL(amazonLink)} > <img src={amazon} alt="amazon-link" /> amazon.in </Button> <Button variant="contained" color="primary" className={styles.flipkartBtn} onClick={() => gotoURL(flipkartLink)} > <img src={flipkart} alt="flipkart-link" /> </Button> </div> </Card> ); }; }
Answer
The problem was I forgot to wrap my routes with CartContext Provider. Here is what I did,
import CartProvider from '../CartContext'; return( <CartProvider> ... Routes <CartProvider> )