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

如何修复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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:24:29