NextJS 13.4中使用Next-Auth登录时出现Hydration错误
问题复现步骤
- 环境版本:
node -v-> v18.16.1npx -v-> 9.8.0
- 使用
npx create-next-app@latest创建基于App目录的Next.js应用 - 通过
npm i next-auth安装NextAuth - 核心实现代码:
- NextAuth路由代码:
import { authOptions } from "@/app/options/authOptions"; import NextAuth from "next-auth/next"; const handler = NextAuth(authOptions) export { handler as GET, handler as POST }- 客户端Session Provider:
"use client"; import React from "react"; import { SessionProvider } from "next-auth/react"; interface Props { children?: React.ReactNode; } export default function NextAuthSessionProvider({ children }: Props) { return ( <SessionProvider> { children } </SessionProvider> ) }- Auth配置选项:
interface User { id: string; name: string; email: string; } export const authOptions: NextAuthOptions = { providers: [ Credentials({ name: "Credentials", credentials: { username: { label: "Username", type: "text", placeholder: "jsmith" }, password: { label: "Password", type: "password" } }, async authorize(credentials, req): Promise<User | null> { if (credentials?.username === "a" && credentials?.password === "b") { return { id: "1", name: "John Smith", email: "john@example.com" }; } else { return null; } } }) ] }- Root Layout代码:
const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body className={inter.className}> <NextAuthSessionProvider>{children}</NextAuthSessionProvider> </body> </html> ) }- 首页代码:
import Link from 'next/link'; export default function Home() { return ( <div> <h1>Home</h1> <Link href={'/dashboard'}> Dashboard </Link> <br /> <Link href={'/api/auth/signin'}> Sign in </Link> <br /> <Link href={'/api/auth/signout'}> Sign out </Link> </div> ) }- 受保护的Dashboard页面:
export default async function DashboardPage() { const session = await getServerSession(authOptions); if (!session) { redirect('/api/auth/signin'); } return ( <div> <h1>Dashboard</h1> <p> This page is only accessible to signed-in users. </p> <Link href={'/'}> Home </Link> <br /> <Link href={'/api/auth/signout'}> Sign out </Link> </div> ) }
错误情况
点击首页的Dashboard链接,会被重定向到/api/auth/signin,输入用户名a、密码b完成登录后,未跳转到预期的/dashboard,反而回到首页/,同时页面出现三个错误。
解决方案
1. 完善Auth配置选项
修改authOptions,补充Session策略、回调函数,确保登录后重定向逻辑和Session序列化正常:
import { NextAuthOptions, CredentialsProvider, Session } from "next-auth"; import { JWT } from "next-auth/jwt"; interface User { id: string; name: string; email: string; } export const authOptions: NextAuthOptions = { providers: [ Credentials({ name: "Credentials", credentials: { username: { label: "Username", type: "text", placeholder: "jsmith" }, password: { label: "Password", type: "password" } }, async authorize(credentials, req): Promise<User | null> { if (credentials?.username === "a" && credentials?.password === "b") { return { id: "1", name: "John Smith", email: "john@example.com" }; } else { return null; } } }) ], // 指定Session存储策略为JWT session: { strategy: "jwt" }, // 处理Session和JWT的序列化,以及登录重定向逻辑 callbacks: { async jwt({ token, user }): Promise<JWT> { if (user) { token.id = user.id; token.name = user.name; token.email = user.email; } return token; }, async session({ session, token }): Promise<Session> { if (session.user) { session.user.id = token.id as string; session.user.name = token.name as string; session.user.email = token.email as string; } return session; }, async signIn({ user, callbackUrl }) { if (user) { // 登录成功后跳转到原本的目标页面,无目标则默认首页 return callbackUrl || "/"; } return false; } }, pages: { signIn: "/api/auth/signin" } };
2. 修改Dashboard页面的重定向逻辑
重定向到登录页时,传递当前页面URL作为回调地址:
import { redirect } from "next/navigation"; import { getServerSession } from "next-auth"; import { authOptions } from "@/app/options/authOptions"; export default async function DashboardPage() { const session = await getServerSession(authOptions); if (!session) { // 传递当前页面作为登录后的跳转目标 redirect(`/api/auth/signin?callbackUrl=${encodeURIComponent("/dashboard")}`); } return ( <div> <h1>Dashboard</h1> <p> This page is only accessible to signed-in users. </p> <Link href={'/'}> Home </Link> <br /> <Link href={'/api/auth/signout'}> Sign out </Link> </div> ) }
3. 清除缓存并重启服务
执行以下命令确保配置生效:
npm run build npm run dev
内容的提问来源于stack exchange,提问作者LoisDuplain
相关产品推荐
相关产品推荐

