Home > Blockchain >  Values getting undefined when consuming data using useContext in the child component
Values getting undefined when consuming data using useContext in the child component

Time:02-22

It is my first time working with useContext hook and I was trying to consume values with useContext in Navbar.js which I've provided in the parent component, but i'm receiving undefined only. In the Navbar.js when I console log user it showsundefined. I tried to pass the data as props and it works fine. It only happens when I try with Context API. I think I messed up my context api implementation.

  1. Created a context at AuthContext.js

import {createContext} from 'react' 

export const AuthContext = createContext({})

  1. Set values in App.js and wrapped using Provider.

import Login from "./pages/Login";
import Register from "./pages/Register";
import Cart from "./components/Cart/Cart";
import Slider from "./components/Slider";
import Categories from "./components/Categories";
import PopularProducts from "./components/PopularProducts";
import Navbar from "./components/Navbar";
import Checkout from "./components/Cart/Checkout";
import Products from "./components/Products";
import Footer from "./components/Footer";
import {
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
  createUserWithEmailAndPassword,
} from "firebase/auth";
import { auth } from "./lib/firebase-config";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { useState, useEffect } from "react";
import { commerce } from "./lib/commerce";
import { AuthContext } from "./context/AuthContext";

const App = () => {
  const [products, setProducts] = useState([]);
  const [cart, setCart] = useState({});
  const [order, setOrder] = useState({});
  const [errorMessage, setErrorMessage] = useState("");
  const [loginEmail, setLoginEmail] = useState("");
  const [loginPassword, setLoginPassword] = useState("");
  const [user, setUser] = useState({});
  const [registerEmail, setRegisterEmail] = useState("");
  const [registerPassword, setRegisterPassword] = useState("");
  const [isLoggedIn, setIsLoggedIn] = useState(
    localStorage.getItem("isLoggedIn")
  );

  onAuthStateChanged(auth, (currentUser) => {
    setUser(currentUser);
  });
  const loginHandler = async (event) => {
    event.preventDefault();

    try {
      const user = await signInWithEmailAndPassword(
        auth,
        loginEmail,
        loginPassword
      );
      setIsLoggedIn(true);
      localStorage.setItem("isLoggedIn", true);
      console.log(auth.currentUser.email);
    } catch (error) {
      console.log(error.message);
    }
  };
  const registerHandler = async () => {
    try {
      const user = await createUserWithEmailAndPassword(
        auth,
        registerEmail,
        registerPassword
      );
      setIsLoggedIn(true);
      localStorage.setItem("isLoggedIn", true);
      console.log({ registerEmail });

      console.log(user);
    } catch (error) {
      console.log(error.message);
    }
  };
  const logoutHandler = async () => {
    await signOut(auth);
    setIsLoggedIn(false);
    localStorage.clear();
  };

  const fetchProducts = async () => {
    const { data } = await commerce.products.list();

    setProducts(data);
  };
  const fetchCart = async () => {
    setCart(await commerce.cart.retrieve());
  };
  const handleAddToCart = async (productId, quantity) => {
    const item = await commerce.cart.add(productId, quantity);

    setCart(item.cart);
  };

  const handleUpdateCartQty = async (lineItemId, quantity) => {
    const response = await commerce.cart.update(lineItemId, { quantity });

    setCart(response.cart);
  };
  const handleRemoveFromCart = async (lineItemId) => {
    const response = await commerce.cart.remove(lineItemId);

    setCart(response.cart);
  };
  const handleEmptyCart = async () => {
    const response = await commerce.cart.empty();

    setCart(response.cart);
  };

  const refreshCart = async () => {
    const newCart = await commerce.cart.refresh();

    setCart(newCart);
  };

  const handleCaptureCheckout = async (checkoutTokenId, newOrder) => {
    try {
      const incomingOrder = await commerce.checkout.capture(
        checkoutTokenId,
        newOrder
      );

      setOrder(incomingOrder);

      refreshCart();
    } catch (error) {
      setErrorMessage(error.data.error.message);
      console.log(error.data);
    }
  };

  useEffect(() => {
    fetchProducts();
    fetchCart();
  }, []);

  return (
    <>
      <AuthContext.Provider
        value={
          (user,
          logoutHandler,
          isLoggedIn) }>
       <Navbar/>
      </AuthContext.Provider>
    </>
  );
};
export default App;

  1. Trying to consume data using useContext in Navbar.js

import { Badge } from "@material-ui/core";
import {
  Search,
  ShoppingCartOutlined,
  TranslateOutlined,
} from "@material-ui/icons";
import { useContext } from "react";
import styled from "styled-components";
import { mobile } from "../responsive";
import { Link } from "react-router-dom";
import { AuthContext } from "../context/AuthContext";

const Parent = styled.div``;
const Container = styled.div`
  height: 70px;
  background-color: #b6e7f0;
  ${mobile({ height: "70px" })}
  width: 98.75vw;
  position: fixed;
  top: 0;
  z-index: 4;
`;

const Logo = styled.h4`
  font-size: 30px;
  color: black;
  margin-left: 20px;
  ${mobile({ fontSize: "30px" })}
`;
const Wrapper = styled.div`
  padding: 10px 0px;
  display: flex;
  justify-content: space-between;
  max-width: 98.75vw;
  ${mobile({ padding: "10px 0px" })}
`;

const Left = styled.div`
  display: flex;
  align-items: center;
  text-decoration: none;
  width: 20%;
`;
const Center = styled.div``;
const Right = styled.div`
  display: flex;
  align-items: center;
  margin-right: 20px;
  justify-content: flex-end;
  text-decoration: none;
  ${mobile({ flex: 2, justifyContent: "flexEnd" })}
`;

const Language = styled.span`
  font-size: 14px;
  cursor: pointer;
  ${mobile({ display: "none" })}
`;
const SearchContainer = styled.div`
  flex: 1;
  display: flex;
  align-items: center;
  margin-left: 0px;
  margin-top: 10px;
  padding: 5 px;
  border-radius: 5px;
  cursor: pointer;

  ${mobile({ display: "none" })}
  &:focus {
  }
`;

const Input = styled.input`
  border: none;

  &:focus {
    outline: none;
  }

  width: 90%;
  height: 100%;
  border-radius: 5px;
  font-size: 15px;
  padding: 5px;
  margin-right: 20px;
  ${mobile({ height: "50%" })}
`;

const MenuItem = styled.div`
  margin-left: 25px;
  margin-top: 3px;
  font-size: 18px;
  font-weight: 600;
  color: #0a6596e6;
  cursor: pointer;
  justify-content: space-between;
  ${mobile({ fontSize: "13px", marginLeft: "10px" })}
`;

const Navbar = () => {
  const { user, logoutHandler, isLoggedIn } = useContext(AuthContext);
  console.log(user)
  return (
    <Parent>
      <Container>
        <Wrapper>
          <Left>
            <Link to={"/"}>
              <Logo>audiobae</Logo>
            </Link>
          </Left>
          <SearchContainer style={{ color: "gray", fontSize: 14 }}>
            <Input placeholder="Search for products, brands and more" />
            <Search style={{ fontSize: "30px" }} />
          </SearchContainer>

          <Right>
            <Language style={{ marginLeft: "5px", marginTop: "3px" }}>
              <TranslateOutlined />
            </Language>
            {console.log(isLoggedIn)}
            {isLoggedIn ? (
              <>
                <MenuItem>{user?.email}</MenuItem>
                <MenuItem onClick={logoutHandler}>Logout</MenuItem>
              </>
            ) : (
              <>
                <Link to={"/register"} style={{ textDecoration: "none" }}>
                  <MenuItem>Register </MenuItem>
                </Link>
                <Link to={"/login"} style={{ textDecoration: "none" }}>
                  <MenuItem>Login</MenuItem>
                </Link>
              </>
            )}
            <MenuItem>
              <Link to={"/cart"}>
                <Badge badgeContent={cart?.total_items} color="primary">
                  {console.log(cart)}
                  <MenuItem>
                    <ShoppingCartOutlined />
                  </MenuItem>
                </Badge>
              </Link>
            </MenuItem>
          </Right>
        </Wrapper>
      </Container>
    </Parent>
  );
};

export default Navbar;

CodePudding user response:

try it

  <AuthContext.Provider value={{user,logoutHandler,isLoggedIn}}>
      <Navbar/>
  </AuthContext.Provider>
  • Related