React Context中googleSignIn为undefined的问题求助
React Context中googleSignIn获取为undefined的原因及解决办法
问题描述
作为React初学者,在使用React Context时遇到问题:调用UserAuth()获取的googleSignIn为undefined。
Context代码
import {useContext, createContext } from 'react'; import { GoogleAuthProvider, signInWithPopup, signOut, onAuthStateChanged } from 'firebase/auth' import { firebaseAuth } from '../Firebase/Config.js' const AuthContext = createContext(); export const AuthContextProvider = ({children}) => { const googleSignIn = async () => { const provider = await new GoogleAuthProvider(); signInWithPopup(firebaseAuth, provider); } return ( <AuthContext.Provider value={googleSignIn}> {children} </AuthContext.Provider> ) } export const UserAuth = () => { return useContext(AuthContext); }
使用Context的代码
import { useState } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import UploadImage from './Firebase/UploadImage.jsx' import './App.css' import {GoogleButton} from 'react-google-button' import { AuthContextProvider, UserAuth } from './Context/AuthContext.jsx' function App() { const googleSignIn = UserAuth(); const handleGoogleSignIn = async () => { console.log(googleSignIn); try { await googleSignIn(); } catch (error) { console.log(error); } } return ( <div> <AuthContextProvider> <UploadImage /> <div className="HandleGoogleSignIn"> <GoogleButton onClick={handleGoogleSignIn} /> </div> </AuthContextProvider> </div> ) } export default App
原因分析
核心问题是**App组件本身不在AuthContextProvider的包裹范围内**。React Context的作用域仅覆盖Provider组件包裹的所有子组件,而你在App组件(Provider的父级)中调用UserAuth(),此时useContext只能拿到createContext()的默认值(你创建Context时未传入默认值,因此返回undefined)。
另外,Context代码里存在一个冗余错误:new GoogleAuthProvider()并非异步操作,不需要添加await,这会导致代码执行异常。
解决办法
方案1:将AuthContextProvider提升到App组件外层
修改项目入口文件(通常为main.jsx或index.jsx),用AuthContextProvider包裹整个App组件,让App处于Context作用域内:
// main.jsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.jsx' import { AuthContextProvider } from './Context/AuthContext.jsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <AuthContextProvider> <App /> </AuthContextProvider> </React.StrictMode>, )
同时修改App.jsx,移除内部的AuthContextProvider:
// App.jsx import { useState } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import UploadImage from './Firebase/UploadImage.jsx' import './App.css' import {GoogleButton} from 'react-google-button' import { UserAuth } from './Context/AuthContext.jsx' function App() { const googleSignIn = UserAuth(); const handleGoogleSignIn = async () => { try { await googleSignIn(); } catch (error) { console.log(error); } } return ( <div> <UploadImage /> <div className="HandleGoogleSignIn"> <GoogleButton onClick={handleGoogleSignIn} /> </div> </div> ) } export default App
方案2:拆分组件,将UserAuth调用移到Provider内部子组件
若不想修改入口文件,可将调用UserAuth()的逻辑拆分为独立子组件,放在AuthContextProvider内部:
// App.jsx import { useState } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import UploadImage from './Firebase/UploadImage.jsx' import './App.css' import {GoogleButton} from 'react-google-button' import { AuthContextProvider, UserAuth } from './Context/AuthContext.jsx' // 拆分出子组件 function GoogleSignInButton() { const googleSignIn = UserAuth(); const handleGoogleSignIn = async () => { try { await googleSignIn(); } catch (error) { console.log(error); } } return ( <div className="HandleGoogleSignIn"> <GoogleButton onClick={handleGoogleSignIn} /> </div> ) } function App() { return ( <div> <AuthContextProvider> <UploadImage /> <GoogleSignInButton /> </AuthContextProvider> </div> ) } export default App
修正Context中的异步错误
最后修改Context里的googleSignIn函数,移除不必要的await,同时为真正的异步操作signInWithPopup添加await:
export const AuthContextProvider = ({children}) => { const googleSignIn = async () => { const provider = new GoogleAuthProvider(); // 移除多余await await signInWithPopup(firebaseAuth, provider); // 为异步操作添加await } return ( <AuthContext.Provider value={googleSignIn}> {children} </AuthContext.Provider> ) }
内容的提问来源于stack exchange,提问作者Dewek
相关产品推荐
相关产品推荐

