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

React Router v6登录后重定向至预订页面的问题解决

React Router v6 登录后重定向至原目标页面的正确实现

问题分析

你当前的实现存在两个核心问题:

  • 拦截逻辑放在Rooms组件里不合理,/book/:roomId是独立路由,无需由Rooms组件负责路径匹配与拦截
  • 登录后重定向的触发逻辑存在优先级问题,可能被AuthContext中默认的页面跳转逻辑覆盖,或者状态更新后的useEffect未正确执行

正确实现方案

1. 实现通用受保护路由组件

创建ProtectedRoute组件,统一处理未认证用户的重定向逻辑,同时完整存储目标路径:

// components/ProtectedRoute.tsx
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';

const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
  const { isAuthenticated } = useAuth();
  const location = useLocation();

  if (!isAuthenticated) {
    // 存储完整目标路径(含查询参数)到sessionStorage,同时通过路由state传递
    const targetPath = location.pathname + location.search;
    sessionStorage.setItem('redirectAfterLogin', targetPath);
    return <Navigate to="/signin" state={{ from: location }} replace />;
  }

  return <>{children}</>;
};

export default ProtectedRoute;

2. 配置路由,用ProtectedRoute保护预订页面

在路由配置文件中,将/book/:roomId路由用ProtectedRoute包裹,替代原有的分散拦截逻辑:

// App.tsx
import { Routes, Route } from 'react-router-dom';
import ProtectedRoute from './components/ProtectedRoute';
import Rooms from './components/Rooms';
import BookRoom from './components/BookRoom'; // 你的预订页面组件
import SignIn from './components/SignIn';
import Dashboard from './components/Dashboard';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Rooms />} />
      <Route path="/signin" element={<SignIn />} />
      <Route path="/dashboard" element={<Dashboard />} />
      {/* 用ProtectedRoute包裹需要认证的预订页面 */}
      <Route 
        path="/book/:roomId" 
        element={
          <ProtectedRoute>
            <BookRoom />
          </ProtectedRoute>
        } 
      />
    </Routes>
  );
}

export default App;

3. 修改SignIn组件的重定向逻辑

优先读取路由state中的来源路径,再用sessionStorage兜底,最后设置默认跳转路径:

// components/SignIn.tsx
import React, { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';

const SignIn = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const { isAuthenticated } = useAuth();

  useEffect(() => {
    if (isAuthenticated) {
      // 优先级:路由state > sessionStorage > 默认仪表盘
      const targetPath = location.state?.from?.pathname + location.state?.from?.search 
        || sessionStorage.getItem('redirectAfterLogin') 
        || '/dashboard';
      
      // 清除存储的路径,避免重复跳转
      sessionStorage.removeItem('redirectAfterLogin');
      
      // 重定向至目标页面
      navigate(targetPath, { replace: true });
    }
  }, [isAuthenticated, navigate, location.state]);

  // 登录表单处理逻辑示例
  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();
    // 调用登录API,成功后更新AuthContext的认证状态
    // await loginAPI();
    // auth.login(); // 假设AuthContext提供login方法更新isAuthenticated
  };

  return (
    <div>
      <h2>登录</h2>
      <form onSubmit={handleLogin}>
        {/* 表单输入框 */}
        <button type="submit">登录</button>
      </form>
    </div>
  );
};

export default SignIn;

4. 移除Rooms组件中的冗余逻辑

删除原Rooms组件中关于/book路径的匹配与拦截代码,回归组件本身的功能:

// components/Rooms.tsx
import React from 'react';

const Rooms: React.FC = () => {
  return <div>Room List Here</div>;
};

export default Rooms;

关键注意事项

  • 确保AuthContext中的isAuthenticated状态是响应式的,登录成功后会立即触发组件重新渲染
  • 若AuthProvider中存在自动跳转至仪表盘的逻辑,需限制其触发条件(仅当用户直接访问登录页且已认证时执行)
  • 存储location.pathname + location.search可完整保留带查询参数的目标路径,比如/book/123?date=2024-05-20

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:13:21