Next.js13+Supabase在layout.tsx中使用Server Actions的认证问题
解决Next.js 13布局组件中Supabase登录状态判断的Promise问题
你遇到的问题根源是:getSessionStatus()是异步函数,调用它会直接返回一个Promise<boolean>对象,而任何Promise对象在JavaScript条件判断中都会被视为true,所以TypeScript提示这个条件永远为true。
因为你的RootLayout是Next.js 13 App Router下的Server Component(默认就是),不需要用Server Action来获取会话状态,直接在组件内部异步处理即可,修复步骤如下:
1. 将RootLayout改为异步组件
Server Component支持直接使用async/await,不需要额外的Server Action包装。
2. 移除Server Action标记并直接获取会话
把获取会话的逻辑直接放在组件内部,或者抽成单独的异步函数(不需要'use server'),然后await结果。
修改后的完整RootLayout代码:
import Link from 'next/link'; import './globals.css'; import { createServerComponentClient } from "@supabase/auth-helpers-nextjs"; import { Database } from "@/types/supabase"; import { cookies } from "next/headers"; export const metadata = { title: 'Create Next App', description: 'Generated by create next app', }; // 改为async组件 export default async function RootLayout({ children }: { children: React.ReactNode }) { const supabase = createServerComponentClient<Database>({ cookies }); const { data: { session } } = await supabase.auth.getSession(); const isLoggedIn = Boolean(session); return ( <html lang="en"> <head> {/* Add any necessary head tags here */} </head> <body> <nav className="flex items-center justify-between flex-wrap bg-teal-500 p-6"> <div className="flex items-center flex-shrink-0 text-white mr-6"> {/* ... logo code ... */} </div> <div className="block lg:hidden"> {/* ... button code ... */} </div> <div className="w-full block flex-grow lg:flex lg:items-center lg:w-auto"> <div className="text-sm lg:flex-grow"> <Link href="/ingresos" passHref> <span className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white"> Ingresos </span> </Link> </div> <div> {isLoggedIn ? ( <button className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0">Log Out</button> ) : ( <> <button className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0 mr-2">Log In</button> <button className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white lg:mt-0">Sign Up</button> </> )} </div> </div> </nav> <main className="min-h-screen bg-background flex flex-col items-center"> {children} </main> </body> </html> ); }
额外说明
- 如果确实需要在客户端组件中调用这个会话检查逻辑,才需要用Server Action,但你的RootLayout是Server Component,直接异步获取更简单高效。
- 异步Server Component在渲染时会先等待异步操作完成,再返回HTML,不会出现客户端的loading状态(如果需要loading,可以在组件内部添加加载逻辑)。
内容的提问来源于stack exchange,提问作者Vladimirzb
相关产品推荐
相关产品推荐

