如何修复expo-auth-session对接Firebase时的无效Hook调用错误
报错根因
Invalid hook call是因为你违反了React Hook的基本调用规则:Google.useAuthRequest是React Hook,只能在函数组件/自定义Hook的顶层作用域调用,你把它写在了signInWithGoogle这个普通异步函数内部,直接触发了Hook规则校验报错。
除此之外你原有代码还有几个隐性问题:
- 没有把
useAuthRequest返回的弹窗触发方法拿出来,直接对Hook返回值做then调用本身就是错误用法 signInWithCredential方法没有传入你项目初始化的Firebase auth实例,就算Hook问题修好也会报参数错误- 没有监听Firebase的全局登录状态,没法把登录后的用户信息同步到Context里
- config里的
permissions字段是Facebook登录的配置项,Google授权不需要这个字段
修复后可运行代码
import React, { createContext, useContext, useState, useEffect } from 'react' import * as Google from 'expo-auth-session/providers/google'; import * as WebBrowser from 'expo-web-browser'; import { GoogleAuthProvider, onAuthStateChanged, signInWithCredential, signOut, } from "@firebase/auth"; // 替换成你自己项目里初始化Firebase后导出的auth实例路径 import { auth } from './firebaseConfig'; const AuthContext = createContext({}); WebBrowser.maybeCompleteAuthSession(); const config = { androidClientId: "替换成你的安卓客户端ID", iosClientId: "替换成你的iOS客户端ID", expoClientId: "替换成你的Expo客户端ID", scopes: ["profile", "email"], } export const AuthProvider = ({children}) => { const [user, setUser] = useState(null); // 必须在组件顶层调用useAuthRequest,符合Hook调用规则 const [request, response, promptAsync] = Google.useAuthRequest(config); // 监听Google授权返回结果 useEffect(() => { if (response?.type === 'success') { const { idToken, accessToken } = response.authentication; const credential = GoogleAuthProvider.credential(idToken, accessToken); signInWithCredential(auth, credential).catch(err => console.log('Firebase登录异常:', err)); } }, [response]); // 监听Firebase全局登录状态,同步更新Context里的用户信息 useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (currentUser) => { setUser(currentUser); }); return () => unsubscribe(); }, []); const signInWithGoogle = async () => { // 主动触发Google登录授权弹窗 if (request) await promptAsync(); }; const handleSignOut = async () => { await signOut(auth); setUser(null); }; return ( <AuthContext.Provider value ={{ user, signInWithGoogle, handleSignOut, }} > {children} </AuthContext.Provider> ); } export default function useAuth() { return useContext(AuthContext); }
使用说明
- 把代码里的auth导入路径替换成你自己项目的Firebase配置文件导出的auth实例,不要漏传这个参数
- 确保你在Google Cloud控制台配置的OAuth客户端ID和config里填写的三个clientId完全匹配,包名、签名哈希和Expo配置一致,否则会授权失败
- 业务页面调用时直接引入
useAuth,拿到signInWithGoogle方法绑定到按钮点击事件即可,登录成功后用户信息会自动录入Firebase Auth数据库,Context里的user字段会同步更新对应用户信息
内容的提问来源于stack exchange,提问作者altarawy
相关产品推荐
相关产品推荐

