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

Google一键登录正常但常规Google登录失效问题求助

问题分析与解决方案

你的问题核心是One Tap弹窗的关闭事件没被正确监听,再加上启用FedCM后,Google账号服务的事件回调逻辑有变化:

  1. 你之前把切换按钮显示的逻辑绑定在renderButton的click_listener上,但这个回调只有点击Google官方渲染的按钮才会触发,和One Tap弹窗的关闭按钮完全无关。
  2. 启用use_fedcm_for_prompt: true后,One Tap的关闭事件需要用cancel_callback来捕获,这是FedCM规范下的专用回调。

修改后的代码

import React, { useState, useRef, useEffect } from 'react';
import { jwtDecode } from 'jwt-decode';
import axios from 'axios';
import { FcGoogle } from 'react-icons/fc';

const GoogleOneTapLogin = ({ setNavigateHome }) => {
    const googleButton = useRef(null);

    const [displayType, setDisplayType] = useState('flex');
    const [gBtnDisplay, setGBtnDisplay] = useState('none');

    const handleResponse = async (response) => {
        const token = response.credential;
        const { sub: uid, email, name, picture: photoURL } = jwtDecode(token);
        const username = email.split('@')[0];
        const config = {
            headers: {
                'Content-type': 'application/json',
            },
        };
        try {
            const result = await axios.post(
                `${import.meta.env.VITE_APP_SERVER_URL}/api/user/googleSignUp`,
                {
                    uid,
                    email,
                    name,
                    photoURL,
                    username,
                },
                config
            );
            const user = result.data.result;
            window.localStorage.setItem(
                'sketchApp',
                JSON.stringify({ email: user.email, isSignedIn: true })
            );
            setNavigateHome(prev => !prev);
        } catch (error) {
            console.log(error);
            alert('Something went wrong, please try again later.');
        }
    };

    // 组件挂载时初始化Google账号服务,只执行一次
    useEffect(() => {
        if (!window.google) return;
        
        window.google.accounts.id.initialize({
            client_id: import.meta.env.VITE_GOOGLE_CLIENT_ID,
            use_fedcm_for_prompt: true,
            auto_select: true,
            cancel_on_tap_outside: false,
            callback: handleResponse,
            // 新增:监听One Tap弹窗关闭事件
            cancel_callback: () => {
                console.log('One Tap弹窗已关闭');
                setDisplayType('none');
                setGBtnDisplay('flex');
            },
            prompt_parent_id: 'googleButtonId',
            itp_support: true,
            ux_mode: 'popup',
        });

        // 预先渲染常规Google登录按钮(默认隐藏)
        window.google.accounts.id.renderButton(googleButton.current, {
            theme: 'outline',
            size: 'large',
            logo_alignment: 'left',
            locale: 'en_US',
            text: 'continue_with',
            width: 280,
        });
    }, []);

    const handleGoogleLogIn = () => {
        try {
            // 只触发One Tap弹窗,不再重复初始化服务
            window.google.accounts.id.prompt();
        } catch (error) {
            console.log(error);
            alert('Log In Failed. Please try again');
            // One Tap失败时直接切换到常规登录按钮
            setDisplayType('none');
            setGBtnDisplay('flex');
        }
    };

    return (
        <React.Fragment>
            <button
                className="googleButton bg-green-800 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded flex justify-center items-center"
                style={{
                    display: displayType,
                    width: 'fit-content',
                    marginTop: '1rem',
                }}
                onClick={handleGoogleLogIn}
            >
                <FcGoogle className="mr-2 text-2xl" />
                Login with Google
            </button>
            <div 
                id="googleButtonId" 
                style={{ display: gBtnDisplay }} 
                ref={googleButton}
            ></div>
        </React.Fragment>
    );
};

export default GoogleOneTapLogin;

关键改动说明

  • 新增cancel_callback:在初始化配置里添加这个回调,专门监听One Tap弹窗的关闭操作(包括点击关闭按钮、点击弹窗外部),触发后自动切换显示常规Google登录按钮。
  • 初始化逻辑移到useEffect:避免每次点击自定义按钮都重复初始化Google账号服务,减少冗余操作和潜在冲突。
  • 简化handleGoogleLogIn:现在只负责触发One Tap弹窗,初始化和常规按钮渲染都在组件挂载时完成。
  • 修正prompt_parent_id绑定:把该属性对应的DOM元素直接绑定到常规按钮的容器上,符合FedCM的DOM层级要求。

内容的提问来源于stack exchange,提问作者Manas Telavane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:17:39