Next.js官方教程15章认证:登录成功后页面全量刷新问题
实现NextAuth登录后无刷新重定向的方案
1. 关闭NextAuth自动服务器端重定向,改用客户端路由跳转
登录时给signIn方法设置redirect: false,禁用默认的服务器端重定向,然后用Next.js客户端路由工具(App Router用next/navigation的useRouter,Pages Router用next/router的useRouter)手动跳转,这样不会触发全页面刷新,保留站点状态。
示例代码:
import { signIn } from 'next-auth/react'; import { useRouter } from 'next/navigation'; export default function LoginForm() { const router = useRouter(); const handleLogin = async (e) => { e.preventDefault(); const email = e.target.email.value; const password = e.target.password.value; // 关闭自动重定向,获取登录结果 const loginResult = await signIn('credentials', { email, password, redirect: false, }); if (loginResult.ok) { // 客户端无刷新跳转到目标页面 router.push('/dashboard'); } else { // 处理登录失败(比如提示错误信息) alert(loginResult.error || '登录失败'); } }; return ( <form onSubmit={handleLogin}> <input type="email" name="email" placeholder="邮箱" required /> <input type="password" name="password" placeholder="密码" required /> <button type="submit">登录</button> </form> ); }
2. 调整中间件的重定向逻辑(针对受保护路由)
如果中间件原本用Response.redirect拦截未登录用户,保持这个逻辑不变(毕竟未登录时需要服务器端拦截),但登录成功后的跳转完全交给客户端处理,避免服务器端重定向导致的全量刷新。
示例中间件代码:
import { authConfig } from './auth.config'; import NextAuth from 'next-auth'; const { auth } = NextAuth(authConfig); export default auth((req) => { const isLoggedIn = !!req.auth; const isLoginPage = req.nextUrl.pathname === '/login'; // 未登录且不在登录页时,服务器端重定向到登录页 if (!isLoggedIn && !isLoginPage) { return Response.redirect(new URL('/login', req.nextUrl)); } }); export const config = { matcher: ['/dashboard/:path*'], // 只拦截受保护的仪表盘路由 };
3. 监听Session状态自动跳转(可选)
如果登录后Session会自动同步,可以用useSession钩子监听状态变化,一旦检测到有效Session就自动跳转,这种方式更贴合NextAuth的状态管理逻辑。
示例代码:
import { useSession } from 'next-auth/react'; import { useRouter } from 'next/navigation'; import { useEffect } from 'react'; export default function LoginPage() { const { data: session } = useSession(); const router = useRouter(); useEffect(() => { // Session有效时,客户端跳转 if (session) { router.push('/dashboard'); } }, [session, router]); // 登录表单部分... return ( <div> <h1>登录</h1> {/* 表单代码同前 */} </div> ); }
内容的提问来源于stack exchange,提问作者Corey
相关产品推荐
相关产品推荐

