React Router v6:登录后重定向至原请求路由问题求助
解决React Router v6登录后重定向到原请求页面的问题
核心思路
拦截未认证请求时,将用户原本要访问的路径存入路由状态(state),登录成功后读取该状态完成重定向。
步骤1:修改ProtectedRoute组件
在拦截跳转时,把当前要访问的路径通过state传递给登录页:
import { Navigate, useLocation } from 'react-router-dom'; import { useAuth } from '../../hooks/useAuth'; export const ProtectedRoute = ({ children }) => { const { token } = useAuth(); const location = useLocation(); if (!token) { // 将原请求路径存入state,传给登录页 return <Navigate to="/login" state={{ from: location }} />; } return children; };
步骤2:修改useAuth的login函数
让login函数接收重定向目标路径参数,登录成功后完成跳转:
import { createContext, useContext, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { useLocalStorage } from './useLocalStorage'; import { authenticateUser } from '../utils/APIFunctions'; const AuthContext = createContext(undefined); export const AuthProvider = ({ children }) => { const [token, setToken] = useLocalStorage('token', null); const navigate = useNavigate(); const login = async (password, redirectTo) => { let error = ''; try { const res = await authenticateUser(password); if (res?.status === 200 && res?.data[0]?.auth_level > 0) { const time = Date.now(); setToken(password + '-' + time); // 登录成功后跳转到原请求路径,或默认路径 navigate(redirectTo, { replace: true }); } else { if (res.data.name === 'ConnectionError') { error = 'Unable to connect to database.'; } else if (res?.data?.ReturnValue !== 0) { error = 'Error logging into Scheduler.'; } } } catch (err) { error = 'Error logging into Scheduler.'; } return error; }; const logout = () => { setToken(null); navigate('/', { replace: true }); }; const value = useMemo( () => ({ token, login, logout, }), [token] ); return ( <AuthContext.Provider value={value}> {children} </AuthContext.Provider> ); }; export const useAuth = () => { return useContext(AuthContext); };
步骤3:在Login组件中传递原路径
从路由状态中取出原请求路径,登录时传给login函数:
import { useLocation } from 'react-router-dom'; import { useAuth } from '../hooks/useAuth'; export const Login = () => { const auth = useAuth(); const location = useLocation(); // 获取原请求路径,默认值设为你需要的页面(比如'/baglines') const from = location.state?.from?.pathname || '/baglines'; const handleSubmit = async (e) => { e.preventDefault(); const password = e.target.password.value; const error = await auth.login(password, from); // 处理错误提示,比如渲染error内容 }; return ( <form onSubmit={handleSubmit}> <input type="password" name="password" /> <button type="submit">登录</button> {/* 错误提示区域 */} </form> ); };
补充说明
- 用
await替代.then让异步逻辑更清晰,避免回调嵌套 navigate的replace: true选项会替换历史记录,避免用户回退时再次回到登录页- 如果用户直接访问登录页,
location.state会是undefined,所以要设置默认重定向路径
内容的提问来源于stack exchange,提问作者dmikester1
相关产品推荐
相关产品推荐

