Next.js无userToken时从Dashboard跳转Login页面(无闪烁)问题
解决Next.js无userToken时Dashboard跳转Login不闪烁的问题
为什么之前的方法不行?
- Next.js有独立的路由系统,不能混用react-router-dom组件,所以
<Navigate>会抛出上下文错误。 useEffect是组件渲染完成后才执行的逻辑,必然会先短暂显示Dashboard再触发跳转,导致闪烁。
分两种路由方案解决(覆盖Next.js主流版本)
方案1:Pages Router(Next.js 12及更早)
用服务器端校验重定向,在页面渲染前完成判断,完全避免闪烁。
在pages/dashboard.js中添加getServerSideProps:
import DashboardContent from '../components/DashboardContent'; export default function Dashboard() { return <DashboardContent />; } // 服务器端渲染前执行的校验逻辑 export async function getServerSideProps(context) { // 从请求cookie中获取userToken(根据你的存储方式调整,比如后端存的token位置) const userToken = context.req.cookies.userToken; if (!userToken) { return { redirect: { destination: '/auth/login', permanent: false, // 临时重定向(HTTP 302) }, }; } return { props: {} }; // 正常返回页面所需参数 }
如果必须在客户端判断(比如token存在localStorage),可以配合条件渲染避免闪烁:
import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; export default function Dashboard() { const router = useRouter(); const [isAuthenticated, setIsAuthenticated] = useState(null); useEffect(() => { const userToken = localStorage.getItem('userToken'); if (!userToken) { router.push('/auth/login'); } else { setIsAuthenticated(true); } }, [router]); // 校验未完成前不渲染任何内容(或显示加载态) if (isAuthenticated === null) return null; return <div>Dashboard Content</div>; }
方案2:App Router(Next.js 13+)
推荐用全局中间件或Server Component重定向,都是在页面渲染前拦截请求。
方法A:全局中间件(一次配置,覆盖所有受保护路由)
在项目根目录创建middleware.js:
import { NextResponse } from 'next/server'; export function middleware(request) { // 从cookie获取token const userToken = request.cookies.get('userToken')?.value; // 定义需要权限校验的路由列表 const protectedPaths = ['/dashboard', '/profile']; if (protectedPaths.includes(request.nextUrl.pathname) && !userToken) { // 重定向到登录页,保留原路径方便登录后返回 return NextResponse.redirect(new URL('/auth/login', request.url)); } return NextResponse.next(); } // 指定中间件生效的路由范围 export const config = { matcher: ['/dashboard/:path*', '/profile/:path*'], };
方法B:Server Component内直接重定向
在app/dashboard/page.js中:
import { redirect } from 'next/navigation'; import { cookies } from 'next/headers'; export default async function DashboardPage() { const userToken = cookies().get('userToken')?.value; if (!userToken) { // 服务器端直接重定向,客户端不会收到Dashboard内容 redirect('/auth/login'); } return <div>Dashboard Content</div>; }
关于控制台的raised属性警告
这个和跳转逻辑无关,通常是你使用的UI组件(比如Material UI的Button)废弃了raised属性,改用variant="contained"替代即可:
// 替换前 <Button raised>Submit</Button> // 替换后 <Button variant="contained">Submit</Button>
内容的提问来源于stack exchange,提问作者Basharmal
相关产品推荐
相关产品推荐

