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

React Router DOM v6问题:直接输入URL访问私有路由自动重定向至首页

解决React私有路由直接访问URL自动跳转到首页的问题

问题描述

在React项目中配置私有路由与公共路由时,直接输入带路径的URL(如https://localhost:3000/dashboard),页面会自动重定向到首页https://localhost:3000/,怀疑是PrivateRoutes函数导致,但不确定修改方式。

现有代码

App.js

const App = () => {
  const {
    state: { isAuthenticated },
  } = AuthContext();
  function PrivateRoutes() {
    return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
  }

  function PublicRoutes() {
    return isAuthenticated ? <Navigate to="/home" /> : <Outlet />;
  }

  return (
    <BrowserRouter>
      <Routes>
        <Route element={<PrivateRoutes />}>
          <Route path="/*" element={<Layout />} />
        </Route>

        <Route path="*" element={<Error />} />
        <Route path="login" element={<PublicRoutes />}>
          <Route path="/login" element={<Login />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};

Layout.js

const Layout = () => {
  return (
    <Box>
      <Header />

      <Routes>
        <Route index element={<Home />} />
        <Route path="dashboard" element={<Dashboard />} />
        <Route path="transaction" element={<Transaction />} />
        <Route path='/*' element={<Navigate to="/" />} />
      </Routes>

      <Footer />
    </Box>
  );
};

问题原因

页面刷新时,AuthContext的isAuthenticated初始状态为false,导致PrivateRoutes先跳转到/login;等认证状态从本地存储/API加载完成后,PublicRoutes检测到用户已认证,又跳转到首页(/home对应Layout的index路由),最终表现为直接跳转到首页。此外,路由顺序不合理,Error路由会拦截后续的login路由匹配。

解决方案

1. 给AuthContext添加加载状态

在AuthContext中增加isLoading状态,用于标识认证状态是否正在加载:

// AuthContext.js示例
import { createContext, useState, useEffect } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [state, setState] = useState({
    isAuthenticated: false,
    isLoading: true // 初始为加载中
  });

  useEffect(() => {
    // 从本地存储获取认证状态(或调用API验证)
    const authToken = localStorage.getItem('authToken');
    setState(prev => ({
      ...prev,
      isAuthenticated: !!authToken,
      isLoading: false
    }));
  }, []);

  return (
    <AuthContext.Provider value={{ state }}>
      {children}
    </AuthContext.Provider>
  );
};

2. 修改PrivateRoutes和PublicRoutes

在加载状态下不执行重定向,避免中间跳转:

const App = () => {
  const {
    state: { isAuthenticated, isLoading },
  } = AuthContext();

  function PrivateRoutes() {
    if (isLoading) {
      return <div>加载中...</div>; // 可替换为自定义加载组件
    }
    return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
  }

  function PublicRoutes() {
    if (isLoading) {
      return <div>加载中...</div>;
    }
    return isAuthenticated ? <Navigate to="/" replace /> : <Outlet />;
  }

  // ...后续代码
};

3. 调整路由顺序

将login路由放在Error路由之前,避免被兜底路由拦截:

return (
  <BrowserRouter>
    <Routes>
      {/* 私有路由 */}
      <Route element={<PrivateRoutes />}>
        <Route path="/*" element={<Layout />} />
      </Route>

      {/* 登录路由 - 放在Error路由前 */}
      <Route path="login" element={<PublicRoutes />}>
        <Route index element={<Login />} /> {/* 用index简化路径配置 */}
      </Route>

      {/* 兜底错误路由 */}
      <Route path="*" element={<Error />} />
    </Routes>
  </BrowserRouter>
);

4. 优化Layout路由(可选)

将Layout中的兜底路由路径改为*,符合React Router规范:

<Routes>
  <Route index element={<Home />} />
  <Route path="dashboard" element={<Dashboard />} />
  <Route path="transaction" element={<Transaction />} />
  <Route path="*" element={<Navigate to="/" replace />} />
</Routes>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:40:34