NextJS13中Supabase useSession初始返回null致渲染闪现问题
解决NextJS 13中Supabase登录页Auth组件闪现问题
方案1:使用服务端组件(App Router推荐)
NextJS 13 App Router下,服务端组件可在请求阶段直接获取session,提前完成重定向逻辑,完全避免客户端的组件闪现问题。
// app/login/page.js(服务端组件) import { getServerSession } from '@supabase/auth-helpers-nextjs' import { redirect } from 'next/navigation' import AuthClient from './AuthClient' export default async function LoginPage() { const session = await getServerSession() if (session) { redirect('/') } return <AuthClient /> } // app/login/AuthClient.js(客户端组件) 'use client' import { Auth, ThemeSupa } from '@supabase/auth-ui-react' import { useSupabaseClient } from '@supabase/auth-helpers-react' import { Box } from '@mantine/core' export default function AuthClient() { const supabase = useSupabaseClient() return ( <Box sx={{ paddingLeft: '35vw', paddingRight: '35vw', paddingTop: '10vh', }}> <Auth redirectTo="http://localhost:3000" supabaseClient={supabase} theme="dark" appearance={{ theme: ThemeSupa }} providers={['google', 'github', 'linkedin']} /> </Box> ) }
服务端组件会在请求时先校验session,若用户已登录直接重定向至首页,不会向客户端发送Auth组件的渲染代码,从根源上解决闪现问题。
方案2:客户端组件添加加载状态退避
如果必须使用客户端组件,可通过useSession返回的status字段判断会话加载状态,在加载完成前显示占位内容,避免Auth组件提前渲染。
'use client' import { Auth, ThemeSupa } from '@supabase/auth-ui-react' import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react' import { Box, Loader } from '@mantine/core' import { useRouter } from 'next/router' import { useEffect } from 'react' export default function AuthComp() { const supabase = useSupabaseClient() const { data: session, status } = useSession() const router = useRouter() useEffect(() => { if (status === 'authenticated') { router.push('/') } }, [status, router]) // 会话加载中时显示加载器 if (status === 'loading') { return ( <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}> <Loader size="lg" /> </Box> ) } // 未登录时渲染Auth组件 if (status === 'unauthenticated') { return ( <Box sx={{ paddingLeft: '35vw', paddingRight: '35vw', paddingTop: '10vh', }}> <Auth redirectTo="http://localhost:3000" supabaseClient={supabase} theme="dark" appearance={{ theme: ThemeSupa }} providers={['google', 'github', 'linkedin']} /> </Box> ) } // 已登录时返回空,等待useEffect触发重定向 return null }
status字段包含loading、authenticated、unauthenticated三种状态,通过它精准控制渲染逻辑,避免未完成校验时显示登录界面。
方案3:使用Middleware全局拦截
通过NextJS Middleware在请求到达页面之前就校验用户会话,直接重定向已登录用户,完全绕过登录页的渲染流程。
创建middleware.js文件:
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' import { NextResponse } from 'next/server' export async function middleware(req) { const res = NextResponse.next() const supabase = createMiddlewareClient({ req, res }) const { data: { session } } = await supabase.auth.getSession() // 已登录用户访问登录页时,直接重定向至首页 if (session && req.nextUrl.pathname === '/login') { return NextResponse.redirect(new URL('/', req.url)) } return res } // 指定中间件生效的路径 export const config = { matcher: ['/login'], }
Middleware在服务端层面拦截请求,提前完成会话校验,已登录用户根本不会加载登录页组件,彻底解决闪现问题。
内容的提问来源于stack exchange,提问作者Victor M
相关产品推荐
相关产品推荐

