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
相关产品推荐
相关产品推荐

