在子组件中使用 useContext 使用数据时值变得不确定

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

这是我第一次使用 useContext 挂钩,我试图使用父组件中提供的 Navbar.js 中的 useContext 使用值,但我只收到 undefined .在 Navbar.js 中,当我控制台日志 user 时,它显示 undefined。 我尝试将数据作为道具传递,但效果很好。它仅在我尝试使用 Context API 时发生。我想我搞砸了我的上下文 api 实现。

  1. AuthContext.js
  2. 创建了上下文

import {createContext} from 'react' 

export const AuthContext = createContext({})

  1. App.js 中设置值并使用 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. 正在尝试使用 Navbar.js
  2. 中的 useContext 使用数据

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;

试一试

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