firebase 用户未定义,尽管它存在

56lgkhnf  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(479)

我正在构建一个react应用程序,但应用程序组件没有接收到我的用户值,即使它存在。我在其他组件上使用了相同的语法,它工作得很好。
我得到的错误是:
未捕获的类型错误:无法解构“(0,context_AuthContext__WEBPACK_IMPORTED_MODULE_2_”的属性“user”。UserAuth)(...)',因为它是未定义的。
下面是我的App代码:

import React, { useState, useEffect } from "react";
import { Drawer, Login, Logout, Signup, ForgotPassword, UpdateProfile, JoinedClasses } from "./components";
import { BrowserRouter as Router, Routes, Route} from "react-router-dom";
import { UserAuth, AuthProvider } from "./context/AuthContext";
import PrivateRoutes from "./Routes/PrivateRoutes";
import { db } from './FireBase/Firebase'
import { doc, collection, onSnapshot } from 'firebase/firestore';

function App() {

  const { user } = UserAuth() 
  const [createdClasses, setCreatedClasses] = useState([])
  const [joinedClasses, setJoinedClasses] = useState([]);

  console.log(user)
  useEffect(() => {

    if (user) {
      const createdClassesRef = collection(doc(db, "Created Classes", user), "Classes");
      const unsubscribe = onSnapshot(createdClassesRef, (snapshot) => {
        setCreatedClasses(snapshot.docs.map((doc) => doc.data()));
      });
      return () => unsubscribe();
    }
  }, [user]);
  
  console.log(createdClasses)

  useEffect(() => {
    if (user) {
      const joinedClassesRef = collection(doc(db, "JoinedClasses", user), "classes");
      const unsubscribe = onSnapshot(joinedClassesRef, (snapshot) => {
        setJoinedClasses(snapshot.docs.map((doc) => doc.data().joinedData));
      });
      return () => unsubscribe();
    }
  }, [user]);

  console.log(joinedClasses)

  return (
    <Router>
      <AuthProvider>
        <Routes>
          <Route exact path="/" element={
          <PrivateRoutes>
            <Drawer />
            <ol>
              {createdClasses.map((item) => (
                <JoinedClasses classData={item} />
              ))}
              {joinedClasses.map((item) => (
                <JoinedClasses classData={item} />
              ))}
            </ol>
            </PrivateRoutes>} />
          <Route path="/update-profile" element={<PrivateRoutes><UpdateProfile /></PrivateRoutes>} />
          <Route path="/logout" element={<PrivateRoutes><Logout /></PrivateRoutes>} />
          <Route path="/login" element={<Login />} />
          <Route path="/signup" element={<Signup />} />
          <Route path="/forgot-password" element={<ForgotPassword />} />
        </Routes>
      </AuthProvider>
    </Router>
  );
}

export default App;

下面是我的AuthContext:

import React, { createContext, useContext, useState, useEffect } from "react"
import { auth } from "../FireBase/Firebase"
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut, updateEmail, updatePassword } from "firebase/auth"
import { GoogleAuthProvider, signInWithRedirect, sendPasswordResetEmail } from "firebase/auth";

const AuthContext = createContext()

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState({})
  // const [user, setUser] = useState(null)
  const [loading, setLoading] = useState(true)

  const googleSignIn = () => {
    const provider = new GoogleAuthProvider();
    // signInWithPopup(auth, provider)
    signInWithRedirect(auth, provider)
  }

  const createUser = (email, password) => {
    return createUserWithEmailAndPassword(auth, email, password)
  }

  const signIn= (email, password) => {
    return signInWithEmailAndPassword(auth, email, password)
  }

  const logout = () => {
    return signOut(auth)
  }

  const resetPassword = (email) => {
    return sendPasswordResetEmail(auth, email)
  }

  const newEmail= (email) => {
    return updateEmail(user, email)
  }

  const newPassword = (password) => {
    return updatePassword(user, password)
  }

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(currentUser => {
      setUser(currentUser)
      setLoading(false)
      console.log('User', currentUser)
    })

    return unsubscribe
  }, [])

  const value = {
    user,
    createUser,
    googleSignIn,
    signIn,
    logout,
    resetPassword,
    newEmail,
    newPassword
  }

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  )
  
}

export const UserAuth = () => {
  return useContext(AuthContext)
}

我想定义用户值,以便从firebase获取文档。
我不明白我这次做错了什么。
请帮帮我

ilmyapht

ilmyapht1#

您的<AuthContext.Provider>需要位于组件树中比您调用useContext(AuthContext);的位置更高的位置。因此,您可能希望将组件拆分为两部分,一个呈现提供程序的父部分和一个使用它的子部分。

function App () {
  return (
    <AuthProvider>
      <Main/>
    </AuthProvider>
  )
}

function Main () {
  const { user } = UserAuth() 
  const [createdClasses, setCreatedClasses] = useState([])
  const [joinedClasses, setJoinedClasses] = useState([]);

  // ...

  return (
    <Router>
      <Routes>
       // ...
      </Routes>
    <Router>
  );
}

另外,自定义钩子的惯例是以小写字母use开始命名,如useAuthuseUserAuth。我建议使用其中一个名称,而不是UserAuth。如果你使用像eslint这样的工具(我推荐使用),如果你不遵循命名约定,它会抱怨。

相关问题