刷新/course页面时useEffect未触发,登录按钮卡在加载状态
问题原因与解决方案
核心问题
最关键的问题是**SiteHeader组件未声明为客户端组件**,同时useEffect缺少依赖数组导致潜在逻辑异常。
在Next.js中,使用useState、useEffect、useRouter这类客户端钩子,或者createClientComponentClient这类客户端专属Supabase API的组件,必须添加'use client'指令——否则客户端钩子完全不会执行,这就是刷新/course页面时useEffect未调用、按钮卡在“Loading”的根本原因。
另外,/course页面是服务器组件,会在服务器端完成会话校验与跳转,但未声明为客户端组件的SiteHeader在客户端 hydration 阶段无法激活钩子逻辑,进一步加剧了问题。
修复步骤
1. 修复SiteHeader组件
在组件最顶部添加客户端组件声明,并修正useEffect的依赖数组:
'use client' // 必须添加这一行,标记为客户端组件 import { useState, useEffect } from 'react' import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' import { useRouter } from 'next/navigation' // 导入其他必要组件... export function SiteHeader() { const supabase = createClientComponentClient<Database>() const router = useRouter() const [usersession, setUser] = useState(false) const [loading, setLoading] = useState(true) const handleSignOut = async () => { if (usersession) { const { error } = await supabase.auth.signOut() if (!error) { setUser(false) router.refresh() } else { console.error("Error signing out:", error) } } else { console.log("user is not logged in") router.push("/authentication") } } // 添加空依赖数组,确保仅在组件挂载功用\_重林明确赋值的特殊逻辑Book批量宝 construct useEffect(() => { console.log("useEffect is called") const fetchUser = async () => { try { const { data: { session } } = await supabase.auth.getSession() setUser(!!session?.user) // 简化状态赋值逻辑 } catch (error) { console.error("Error fetching session:", error) setUser(false) } finally { setLoading(false) } } fetchUser() }, []) // 空依赖数组:仅组件挂载时执行一次 return ( <header className="sticky top-0 z-40 w-full border-b bg-background"> <div className="container flex items-center h-16 space-x-4 sm:justify-between sm:space-x-0"> <MainNav items={siteConfig.mainNav} /> <div className="flex items-center justify-end flex-1 space-x-4"> <nav className="flex items-center space-x-1"> <Button onClick={handleSignOut} // 无需额外async包裹,函数本身已是async > {loading ? "Loading..." : usersession ? "Sign Out" : "Sign In"} </Button> </nav> </div> </div> </header> ) }
2. 优化CourseHomePage会话处理(可选)
将会话校验逻辑提前,避免无会话时执行不必要的数据库查询:
import { getSession } from '@supabase/auth-helpers-nextjs' import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' import { redirect } from 'next/navigation' const CourseHomePage = async () => { const session = await getSession() // 提前校验会话,无会话直接跳转 if (!session) { return redirect("/authentication") } // 会话存在时再执行数据库查询 const supabase = createClientComponentClient<Database>() const { data: supabase_data, error } = await supabase .from("payment") .select() .eq("created_by", session.user.id) .eq("is_success", true) if (error) { console.error("Error fetching payment data:", error) } // 渲染页面内容... }
内容的提问来源于stack exchange,提问作者Cai
相关产品推荐
相关产品推荐

