You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:57:32