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

React Router v6认证后页面不跳转,仅刷新才生效的正确解决方法

React Router v6登录后页面不跳转问题解决方法

你的问题根源在于路由配置中authToken是初始化时一次性读取的,登录成功后localStorage的token更新了,但这个变量不会自动重新计算,导致路由的条件渲染逻辑没有触发更新,所以URL变了但页面组件没切换。以下是正确的处理方案:

步骤1:创建认证路由组件

通过封装受保护路由和公共路由组件,动态判断用户认证状态:

受保护路由(仅已登录用户可访问)

创建components/ProtectedRoute.jsx:

import { Navigate } from 'react-router-dom';

const ProtectedRoute = ({ children }) => {
  const isAuthenticated = localStorage.getItem("token") != null;
  return isAuthenticated ? children : <Navigate to="/auth/login" replace />;
};

export default ProtectedRoute;

公共路由(已登录用户自动跳转首页)

创建components/PublicRoute.jsx:

import { Navigate } from 'react-router-dom';

const PublicRoute = ({ children }) => {
  const isAuthenticated = localStorage.getItem("token") != null;
  return isAuthenticated ? <Navigate to="/home" replace /> : children;
};

export default PublicRoute;

步骤2:重构路由配置

修改路由文件,使用上面的路由组件替代固定的条件判断:

import * as React from "react";
import * as ReactDOM from "react-dom/client";
import {
  createBrowserRouter,
  createRoutesFromElements,
  Route,
  RouterProvider,
  Navigate
} from "react-router-dom";

import "./index.css";
import HomePage from "./pages/HomePage";
import NotFound from "./pages/NotFound";
import LoginPage from "./pages/LoginPage";
import RegisterPage from "./pages/RegisterPage";
import ProtectedRoute from './components/ProtectedRoute';
import PublicRoute from './components/PublicRoute';

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route errorElement={<NotFound />}>
      {/* 默认路由自动跳转 */}
      <Route path="/" element={<Navigate to="/home" replace />} />
      {/* 首页:仅已登录用户可访问 */}
      <Route path="home" element={
        <ProtectedRoute>
          <HomePage />
        </ProtectedRoute>
      } />
      {/* 登录页:已登录自动跳转首页 */}
      <Route path="auth/login" element={
        <PublicRoute>
          <LoginPage />
        </PublicRoute>
      } />
      {/* 注册页:已登录自动跳转首页 */}
      <Route path="auth/register" element={
        <PublicRoute>
          <RegisterPage />
        </PublicRoute>
      } />
    </Route>
  )
);

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

步骤3:修复登录组件

移除强制刷新的navigate(0),仅保留跳转逻辑:

import React, { useState } from "react";
import axios from "axios";
import { Button, Typography, Box, TextField } from "@mui/material";
import { useNavigate } from "react-router-dom";

const LoginPage = () => {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const navigate = useNavigate();

  const handleLogin = async () => {
    const data = {
      username,
      password,
    };

    try {
      const response = await axios.post(
        "http://localhost:3001/auth/login",
        data
      );
      localStorage.setItem("token", response.data.token);
      // 直接跳转首页,路由组件会自动处理认证状态
      navigate("/home", { replace: true });
      
      console.log(localStorage.getItem("token"));
    } catch (error) {
      console.error("登录失败:", error);
    }
  };

  return (
    <Box sx={{ maxWidth: 400, margin: '0 auto', padding: 3 }}>
      <Typography variant="h4" gutterBottom>登录</Typography>
      <TextField
        fullWidth
        label="用户名"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        margin="normal"
      />
      <TextField
        fullWidth
        label="密码"
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        margin="normal"
      />
      <Button 
        fullWidth
        onClick={handleLogin} 
        variant="contained" 
        color="primary"
        sx={{ marginTop: 2 }}
      >
        登录
      </Button>
    </Box>
  );
};

export default LoginPage;

额外说明

  • navigate的replace: true参数可以避免用户点击返回按钮回到登录页,优化体验。
  • 如果需要在多个组件中共享认证状态,建议使用React Context或状态管理库(如Redux),让状态变化时所有依赖组件自动重渲染。

内容的提问来源于stack exchange,提问作者amorim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:25:59