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

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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:38:20