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

Next.js中如何让handleSignInWithGoogle函数全局可用?

在Next.js中实现Supabase Google预构建OAuth的全局回调函数

问题原因

你在layout.tsx的JSX里直接写<script>标签导致语法错误,因为Next.js的App Router中,JSX内的脚本需要用next/script组件适配,且直接定义全局函数的方式要适配客户端环境,同时需将函数挂载到window对象上。

正确实现方式

方法1:使用next/script组件(推荐,适配App Router)

在layout.tsx中导入next/script,通过它注入全局函数,同时确保Supabase客户端在客户端环境初始化:

import Script from 'next/script';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {/* 注入全局回调函数 */}
        <Script id="google-oauth-callback" strategy="afterInteractive">
          {`
            async function handleSignInWithGoogle(response) {
              // 调用全局挂载的Supabase客户端
              const { data, error } = await window.supabase.auth.signInWithIdToken({
                provider: 'google',
                token: response.credential,
              });
              if (error) console.error('登录失败:', error);
            }
          `}
        </Script>

        {/* 全局初始化Supabase客户端 */}
        <Script id="supabase-client" strategy="beforeInteractive">
          {`
            import { createClient } from '@supabase/supabase-js';
            window.supabase = createClient('你的SUPABASE_URL', '你的SUPABASE_ANON_KEY');
          `}
        </Script>

        {children}
      </body>
    </html>
  );
}

方法2:在客户端组件中挂载函数到window

创建专门的客户端组件(如GoogleAuthCallback.tsx),在组件内将函数挂载到window对象:

// app/components/GoogleAuthCallback.tsx
'use client';

import { useEffect } from 'react';
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

export default function GoogleAuthCallback() {
  useEffect(() => {
    // 挂载到window全局作用域
    window.handleSignInWithGoogle = async (response: any) => {
      const supabase = createClientComponentClient();
      const { data, error } = await supabase.auth.signInWithIdToken({
        provider: 'google',
        token: response.credential,
      });
      if (error) console.error('登录出错:', error);
    };

    // 组件卸载时清理全局函数
    return () => {
      delete window.handleSignInWithGoogle;
    };
  }, []);

  return null;
}

随后在layout.tsx中引入该组件:

import GoogleAuthCallback from './components/GoogleAuthCallback';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <GoogleAuthCallback />
        {children}
      </body>
    </html>
  );
}

额外注意事项

  • 必须确保Supabase客户端在客户端环境初始化,不能在服务端组件中直接调用signInWithIdToken
  • 使用TypeScript时,需扩展Window接口避免类型报错:
// app/types/global.d.ts
declare global {
  interface Window {
    supabase: import('@supabase/supabase-js').SupabaseClient;
    handleSignInWithGoogle: (response: any) => Promise<void>;
  }
}

export {};

内容的提问来源于stack exchange,提问作者Phil Lucks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:47:25