You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:05:30