React Router V6中useNavigate登录后跳转失效问题求助
登录后跳转异常问题
登录成功后调用navigate("/modules"),目标页面仅在URL中短暂显示,随即被PublicRoute组件重定向至/welcome页面。推测原因是登录前处于PublicRoutes下的登录页,登录成功后该路由变为禁止访问状态,触发了PublicRoutes的默认重定向,覆盖了登录流程中指定的跳转目标。
相关代码
应用入口与路由结构
main.jsx
ReactDOM.createRoot(document.getElementById('root')).render( <BrowserRouter> <AuthContextProvider> <App /> </AuthContextProvider> </BrowserRouter> )
App.jsx
function App() { return ( <Routes> <Route path='/' element={<SharedLayout/>}> <Route element={<PrivateRoutes/>}> <Route path="/welcome" element={<PrivateHome/>}/> <Route path="/modules" element={<Modules/>}/> </Route> <Route element={<PublicRoutes/>}> <Route path="/" element={<PublicHome/>}/> <Route path="/login" element={<Login/>}/> <Route path="/signup" element={<Signup/>}/> </Route> </Route> </Routes> ) }
路由守卫组件
PrivateRoutes.jsx
function PrivateRoutes ({children, ...rest}) { const {user} = UserAuth() if (user===undefined) return <Loading/> return ( user ? <Outlet/>: <Navigate to="/login"/> ) }
PublicRoutes.jsx
import React from 'react' import { Outlet, Navigate } from 'react-router-dom' import Loading from '../components/Loading' import { UserAuth } from './AuthContext' function PublicRoutes ({children}) { const {user} = UserAuth() if (user===undefined) return <Loading/> return ( user ? <Navigate to="/welcome"/> : <Outlet/> ) }
登录组件与认证上下文
Login.jsx
const handleLogin = async (e) => { e.preventDefault() try { await login(email, password) navigate("/modules") } catch (error) { console.log(error) setPassword("") } }
AuthContext.jsx
const AuthContext = createContext() export const AuthContextProvider = ({children})=> { const [user, setUser] = useState(undefined) // undefined -> loading状态 const login = (email, password) => { return signInWithEmailAndPassword(auth, email, password) } useEffect(()=> { const unsubscribe = onAuthStateChanged(auth, async (currentUser) => { setUser(currentUser) }) return ()=> { unsubscribe() } }, []) return ( <AuthContext.Provider value={{user, login}}> {children} </AuthContext.Provider> ) } export const UserAuth = () => { return useContext(AuthContext) }
补充说明:普通navigate调用在其他场景下正常工作,仅在公共路由与私有路由切换时出现异常。
解决方案
核心问题分析
登录成功后,onAuthStateChanged会异步更新user状态,此时PublicRoutes检测到用户已登录,会触发重定向到/welcome,覆盖了登录时的navigate("/modules")操作。
具体修复步骤
修改PublicRoutes逻辑,允许已登录用户临时访问登录/注册页
调整路由守卫逻辑,当用户已登录时,若当前处于登录或注册页则允许停留,否则再重定向:import React from 'react' import { Outlet, Navigate, useLocation } from 'react-router-dom' import Loading from '../components/Loading' import { UserAuth } from './AuthContext' function PublicRoutes ({children}) { const {user} = UserAuth() const location = useLocation() const allowedPublicPaths = ['/login', '/signup'] if (user===undefined) return <Loading/> if (user) { // 已登录用户在登录/注册页时允许访问,否则重定向 return allowedPublicPaths.includes(location.pathname) ? <Outlet/> : <Navigate to="/welcome"/> } else { return <Outlet/> } }优化登录跳转,使用replace模式覆盖历史记录
在登录成功后的跳转中加入replace: true,替换当前登录页的历史记录,避免后续重定向干扰:// Login.jsx中修改navigate调用 navigate("/modules", { replace: true })
原理说明
- 修改
PublicRoutes后,已登录用户停留在登录/注册页时不会被强制重定向,确保登录流程中的跳转能顺利完成。 - 使用
replace: true会将登录页从历史栈中移除,即使后续有重定向触发,也不会回到登录页,同时保证目标页面成为当前活跃路由。
内容的提问来源于stack exchange,提问作者KidMe
相关产品推荐
相关产品推荐

