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

react-router-dom中<Route>优先级高于useNavigate致登录跳转失效

react-router-dom 登录后跳转逻辑失效问题

问题现象

登录成功后调用navigate("/profile")未生效,页面从/auth被重定向到/,跳转请求被覆盖。

现有代码

AppRoutes 路由配置

return (
    <Routes>
        <Route path="/" element={<Home/>}/>
        {!userStore.isLogin && (
            <>
                <Route path="/profile" element={<Navigate replace to="/auth"/>}/>
                <Route path="/auth" element={<Auth/>}/>
                <Route path="/register" element={<Register/>}/>
            </>
        )}
        {userStore.isLogin && (
            <>
                <Route path="/profile" element={<Profile/>}/>
                <Route path="/auth" element={<Navigate replace to="/"/>}/>
                <Route path="/register" element={<Navigate replace to="/"/>}/>
            </>
        )}
    </Routes>
)

登录逻辑函数 onAuth

const onAuth = async () => {
    const result = await login(data);
    if (result.ok) {
        const localUser = JSON.stringify({
            token: result.token,
            isLogin: true
        })
        localStorage.setItem("user", localUser)
        dispatch(userLogged({token: result.token}));
        navigate("/profile")
    } else {
        setMessage(result?.message || "请求执行时发生错误")
    }
}

问题根源

当前路由配置是基于userStore.isLogin状态直接渲染不同路由组,登录成功后流程冲突:

  1. 调用dispatch(userLogged)更新isLogin状态,组件触发重渲染
  2. 路由规则切换为已登录状态,/auth路由对应的元素变为<Navigate replace to="/"/>
  3. 这个重定向优先于navigate("/profile")执行,直接覆盖了后续跳转请求

解决方案

方案一:用路由守卫(嵌套路由+Outlet)重构路由

通过守卫组件统一处理权限,避免路由规则频繁切换导致的冲突:

import { Outlet, Navigate } from 'react-router-dom';

// 已登录权限守卫
const RequireAuth = () => {
  const { isLogin } = userStore;
  return isLogin ? <Outlet /> : <Navigate replace to="/auth" />;
};

// 未登录权限守卫
const RequireNoAuth = () => {
  const { isLogin } = userStore;
  return isLogin ? <Navigate replace to="/" /> : <Outlet />;
};

// 重构后的路由配置
return (
  <Routes>
    <Route path="/" element={<Home />} />
    
    {/* 仅已登录可访问的路由 */}
    <Route element={<RequireAuth />}>
      <Route path="/profile" element={<Profile />} />
    </Route>
    
    {/* 仅未登录可访问的路由 */}
    <Route element={<RequireNoAuth />}>
      <Route path="/auth" element={<Auth />} />
      <Route path="/register" element={<Register />} />
    </Route>
  </Routes>
);

方案二:调整跳转时机(无需重构路由)

通过useEffect监听isLogin状态变化,确保状态更新完成后再执行跳转:

// 在Auth组件中添加状态监听
const { isLogin } = userStore;
const navigate = useNavigate();

useEffect(() => {
  if (isLogin) {
    navigate("/profile", { replace: true });
  }
}, [isLogin, navigate]);

// 修改后的登录函数
const onAuth = async () => {
    const result = await login(data);
    if (result.ok) {
        const localUser = JSON.stringify({
            token: result.token,
            isLogin: true
        })
        localStorage.setItem("user", localUser)
        dispatch(userLogged({token: result.token}));
        // 移除直接调用的navigate,交给useEffect处理
    } else {
        setMessage(result?.message || "请求执行时发生错误")
    }
}

方案说明

  • 方案一通过固定路由规则+守卫组件的方式,统一处理权限校验,彻底避免路由切换导致的重定向冲突
  • 方案二利用状态监听确保跳转时机晚于路由规则更新,解决顺序执行的覆盖问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:18:14