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

React Router中登录后如何重定向至指定页面?

在React Router中实现登录后重定向至指定页面

针对你描述的「未登录时尝试搜索,弹窗登录后跳转至搜索结果页」场景,核心思路是先记录用户原本要访问的目标路径及参数,登录成功后根据记录信息完成跳转。以下是基于React Router v6的具体实现方案:

方案1:跳转至登录页面,通过location.state传递目标信息

这种方式适合需要单独登录页面的场景,用户点击搜索后跳转到登录页,登录完成后自动跳转回目标页。

1. 搜索组件:拦截未登录操作,传递目标路径

import { useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext'; // 自定义鉴权Hook

function SearchBar() {
  const navigate = useNavigate();
  const { isLoggedIn } = useAuth();

  const handleSearch = (searchQuery) => {
    if (!isLoggedIn) {
      // 把目标页面路径和搜索参数存入location.state
      navigate('/login', {
        state: {
          from: '/search-results',
          searchParams: { q: searchQuery }
        }
      });
    } else {
      // 已登录直接跳转至搜索结果页
      navigate(`/search-results?q=${searchQuery}`);
    }
  };

  return (
    <input 
      type="text" 
      placeholder="输入关键词搜索"
      onChange={(e) => handleSearch(e.target.value)} 
    />
  );
}

2. 登录组件:获取目标信息,登录后跳转

import { useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext';

function Login() {
  const location = useLocation();
  const navigate = useNavigate();
  const { login } = useAuth();

  // 从location.state提取目标路径,默认跳首页
  const redirectTarget = location.state?.from || '/';
  const targetParams = location.state?.searchParams || {};

  const handleLogin = async (credentials) => {
    // 调用登录API,这里用Promise模拟
    const loginSuccess = await login(credentials);
    
    if (loginSuccess) {
      // 拼接带参数的目标URL
      const targetUrl = new URL(redirectTarget, window.location.origin);
      Object.entries(targetParams).forEach(([key, val]) => {
        targetUrl.searchParams.append(key, val);
      });
      
      // 跳转并替换历史记录,避免回退到登录页
      navigate(targetUrl.pathname + targetUrl.search, { replace: true });
    }
  };

  return (
    <div className="login-form">
      <input type="email" placeholder="邮箱" />
      <input type="password" placeholder="密码" />
      <button onClick={() => handleLogin({ email: 'user@example.com', password: '123456' })}>
        登录
      </button>
    </div>
  );
}

方案2:弹窗登录,通过全局状态存储目标信息

如果希望在当前页弹出登录弹窗(不跳转页面),可以用Context存储跳转目标,登录成功后直接跳转。

1. 鉴权Context:管理登录状态和跳转信息

// AuthContext.js
import { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [redirectState, setRedirectState] = useState(null);
  const [showLoginModal, setShowLoginModal] = useState(false);

  // 模拟登录API
  const login = async (credentials) => {
    await new Promise(resolve => setTimeout(resolve, 1000));
    setIsLoggedIn(true);
    return true;
  };

  return (
    <AuthContext.Provider 
      value={{ 
        isLoggedIn, 
        login, 
        redirectState, 
        setRedirectState,
        showLoginModal,
        setShowLoginModal 
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

2. 搜索组件:触发弹窗并记录目标路径

import { useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext';

function SearchBar() {
  const navigate = useNavigate();
  const { isLoggedIn, setRedirectState, setShowLoginModal } = useAuth();

  const handleSearch = (searchQuery) => {
    if (!isLoggedIn) {
      // 存储目标页面和参数
      setRedirectState({
        path: '/search-results',
        searchParams: { q: searchQuery }
      });
      // 弹出登录弹窗
      setShowLoginModal(true);
    } else {
      navigate(`/search-results?q=${searchQuery}`);
    }
  };

  return (
    <input 
      type="text" 
      placeholder="输入关键词搜索"
      onChange={(e) => handleSearch(e.target.value)} 
    />
  );
}

3. 登录弹窗组件:登录完成后跳转

import { useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext';

function LoginModal() {
  const navigate = useNavigate();
  const { login, redirectState, showLoginModal, setShowLoginModal, setRedirectState } = useAuth();

  const handleLogin = async (credentials) => {
    const loginSuccess = await login(credentials);
    
    if (loginSuccess) {
      setShowLoginModal(false);
      
      if (redirectState) {
        const { path, searchParams } = redirectState;
        const targetUrl = new URL(path, window.location.origin);
        Object.entries(searchParams).forEach(([key, val]) => {
          targetUrl.searchParams.append(key, val);
        });
        
        navigate(targetUrl.pathname + targetUrl.search, { replace: true });
        // 清空跳转状态
        setRedirectState(null);
      } else {
        navigate('/');
      }
    }
  };

  if (!showLoginModal) return null;

  return (
    <div className="modal-overlay">
      <div className="modal-content">
        <input type="email" placeholder="邮箱" />
        <input type="password" placeholder="密码" />
        <button onClick={() => handleLogin({ email: 'user@example.com', password: '123456' })}>
          登录
        </button>
        <button onClick={() => setShowLoginModal(false)}>取消</button>
      </div>
    </div>
  );
}

关键注意点

  • 使用location.state传递敏感/临时信息,不会暴露在URL中,比URL参数更安全。
  • 登录跳转时添加replace: true,将登录页从浏览器历史栈中移除,避免用户回退到登录页。
  • 弹窗场景下,登录成功后记得清空存储的跳转状态,避免后续逻辑异常。

内容的提问来源于stack exchange,提问作者Md Uzzal Hossain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 12:18:08