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
相关产品推荐
相关产品推荐

