在我的 NextJS15 项目中,我的导航栏有一个 sign in / sign out 组件。我正在使用 Supabase auth(使用密码和电子邮件登录)。
我的登录/退出按钮的行为有问题。
预期的行为是:
我当前的代码给了我什么
代码看起来像这样
export default function AuthButton() {
const router = useRouter();
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
const [isLoading, setIsLoading] = useState(true);
const supabase = createClient();
useEffect(() => {
const { data } = supabase.auth.onAuthStateChange((event, session) => {
if (event === "SIGNED_IN" || event === "INITIAL_SESSION") {
setIsAuthenticated(!!session);
} else if (event === "SIGNED_OUT") {
setIsAuthenticated(false);
router.push("/login");
}
setIsLoading(false);
});
return () => {
data.subscription.unsubscribe();
};
}, [router, supabase.auth]);
const handleSignOut = async () => {
try {
await supabase.auth.signOut();
} catch (error) {
console.error("Error signing out:", error);
}
};
if (isAuthenticated) {
return (
<>
{isLoading ? (
<div className="pl-5 pt-3">
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
</div>
) : (
<Button variant="ghost" onClick={handleSignOut} aria-label="Sign out">
Sign Out
</Button>
)}
</>
);
}
return (
<Button asChild variant="ghost" aria-label="Sign in">
<Link href="/login">Sign In</Link>
</Button>
);
}
预先感谢您的帮助。
我建议不要让您的 AuthButton 处理您拥有的身份验证状态。
您如何处理服务器端的事情?
说实话,我会完全重写你的AuthButton。我会安装中间件来处理用户状态,然后只有一个 AuthButton 组件来检查是否有用户。
完成中间件设置后,这将是您的新 AuthButton 组件:
export async function AuthButton() {
const supabase = await supabaseServer();
const {
data: { user },
} = await supabase.auth.getUser();
return (
<Link
className="btn btn-primary"
href={user ? "/auth/signout" : "/auth/signin"}
>
{user ? "Sign Out" : "Sign in"}
</Link>
);
}
/auth/signout 是一个路由处理程序,它将注销用户并在注销后重定向到您想要的任何页面。
supabaseServer() 来自 SSR 包,该包是从此处找到的 Supabase 指南引用的:https://supabase.com/docs/guides/auth/server-side/nextjs
此外,我还为任何想要使用命令
npx next-mods
在大约一分钟内将 Supabase 身份验证正确添加到其 Next.js 项目的人开发了一个 CLI 工具。如果你想尝试一下,我很乐意提供反馈。希望这有帮助!