React注销后PrivateRoute仍可访问仪表盘的问题排查
问题:注销后仍能通过返回按钮/URL访问受保护的仪表盘路由
我正在编写简单的React页面巩固知识点,采用将登录信息存储在users.json文件中的简易认证方式。目前遇到的问题是:注销操作完成后,点击浏览器返回按钮会回到仪表盘页面;直接在URL栏输入/dashboard也能进入该页面。明明已经配置了PrivateRoute做路由守卫,却没起到预期作用,想知道问题出在哪。
相关代码
AuthProvider.jsx
import { createContext, useContext, useState } from "react"; import { useNavigate } from "react-router-dom"; import users from "../json/users.json"; const AuthContext = createContext(); const AuthProvider = ({ children }) => { const navigate = useNavigate(); const [user, setUser] = useState(null); const login = (email, password) => { const foundUser = users.find( (u) => u.email === email && u.password === password ); if (foundUser) { console.log("creds match"); setUser(foundUser.email); navigate("/dashboard"); return true; } else { console.log("creds do not match"); return false; } }; const logout = () => { setUser(null); navigate("/login"); }; return ( <AuthContext.Provider value={{ user, login, logout }}> {children} </AuthContext.Provider> ); }; export const useAuth = () => { return useContext(AuthContext); }; export default AuthProvider;
PrivateRoute.jsx
import { Outlet } from "react-router-dom"; import { Navigate } from "react-router-dom"; import { useAuth } from "./AuthProvider" const PrivateRoute = () => { const user = useAuth(); if (!user) return <Navigate to="/login" /> return <Outlet /> } export default PrivateRoute;
App.jsx
import { Routes, Route } from "react-router-dom"; import { BrowserRouter } from "react-router-dom"; import Login from "./components/Login"; import Dashboard from "./components/Dashboard"; import AuthProvider from "./hooks/AuthProvider"; import Navbar from "./components/Navbar"; import Signup from "./components/Signup"; import Home from "./components/Home"; import PrivateRoute from "./hooks/PrivateRoute"; export default function App() { return ( <div className="App"> <BrowserRouter> <AuthProvider> <Navbar /> <Routes> <Route path="/" element={<Home />} /> <Route path="/login" element={<Login />} /> <Route path="/signup" element={<Signup />} /> <Route element={<PrivateRoute />} > <Route path="/dashboard" element={<Dashboard />} /> </Route> </Routes> </AuthProvider> </BrowserRouter> </div> ); }
问题原因
你的PrivateRoute存在一个关键错误:useAuth()返回的是整个上下文对象(包含user、login、logout三个属性),而不是直接的user状态值。
在当前代码中,const user = useAuth();这行拿到的是一个对象,而非null或邮箱字符串。此时!user的判断永远为false(因为对象本身是存在的,不会是null或undefined),所以PrivateRoute一直返回<Outlet />,不会触发重定向,自然无法拦截未授权的访问。
修复方案
1. 修正PrivateRoute的取值逻辑
修改PrivateRoute.jsx,从上下文对象中解构出user:
import { Outlet, Navigate } from "react-router-dom"; import { useAuth } from "./AuthProvider" const PrivateRoute = () => { const { user } = useAuth(); // 解构获取真实的user状态 if (!user) return <Navigate to="/login" /> return <Outlet /> } export default PrivateRoute;
2. 补充页面刷新后的状态持久化(可选但推荐)
当前user状态存在内存中,页面刷新后会丢失,导致已登录用户刷新页面后被踢回登录页。可以通过localStorage持久化状态:
修改AuthProvider.jsx的对应部分:
// 初始化时从localStorage读取状态 const [user, setUser] = useState(() => { return localStorage.getItem('authUser') || null; }); const login = (email, password) => { const foundUser = users.find( (u) => u.email === email && u.password === password ); if (foundUser) { console.log("creds match"); const userEmail = foundUser.email; setUser(userEmail); localStorage.setItem('authUser', userEmail); // 登录时同步到localStorage navigate("/dashboard"); return true; } else { console.log("creds do not match"); return false; } }; const logout = () => { setUser(null); localStorage.removeItem('authUser'); // 注销时清除localStorage navigate("/login"); };
内容的提问来源于stack exchange,提问作者Darsh. S.
相关产品推荐
相关产品推荐

