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

React嵌套路由跳转异常求助:useNavigate与Router使用问题

问题描述

我开发的系统加载后需要用户登录,登录验证通过后进入带有多个菜单的页面(初始无菜单,登录后显示)。我使用Router、useNavigate实现了嵌套路由,但点击菜单显示对应组件时,页面会自动返回菜单根目录。以下是相关代码,请问问题出在哪里?

App.js

import React, { useEffect, useState } from "react";
import { Navigate, Route, Routes, useNavigate } from "react-router-dom";
import "./App.css";
import Container from "./container/Container";
import Router from "./components/clinic/router/Router";
import Message from "./components/clinic/pages/message/Message";
import Mytasks from "./components/clinic/pages/mytasks/Mytasks";
import Members from "./components/clinic/pages/members/Members";
import Calendar from "./components/clinic/pages/calendar/Calendar";

function App() {
  const [IsLoggedIn, setIsLoggedIn] = useState(false);
  const navigate = useNavigate();
  useEffect(() => {
    if (!IsLoggedIn) {
      navigate("/");
    } else {
      navigate("clinic");
    }
  }, [navigate, IsLoggedIn]);
  return (
    <React.Fragment>
      <Routes>
        <Route path="/" element={<Container setIsLoggedIn={setIsLoggedIn} />} />
        <Route path="/clinic" element={<Router />}>
          <Route index element={<Message />} />
          <Route path="mytasks" element={<Mytasks />} />
          <Route path="members" element={<Members />} />
          <Route path="calendar" element={<Calendar />} />
          <Route path="*" element={<Navigate to="/" />} />
        </Route>
        <Route path="*" element={<Navigate to="/" />} />
      </Routes>
    </React.Fragment>
  );
}

export default App;

Router.jsx

<Link to="/clinic">Message</Link>
<Link to="/clinic/mytasks/"> My Tasks </Link>
<Link to="/clinic/members"> Members </Link>
<Link to="/clinic/calendar"> Calendar </Link>
<Outlet />
问题原因与解决方法

核心问题

问题出在App组件的useEffect钩子上:每当IsLoggedIn状态变化时,这个钩子就会触发强制导航。当你点击菜单进入/clinic/mytasks这类子路由时,组件重新渲染,IsLoggedIn仍为true,useEffect就会执行navigate("clinic"),直接把页面重定向回/clinic根目录,刚进入的子路由被覆盖。

另外,Router.jsx中/clinic/mytasks/多了末尾斜杠,虽不是直接原因,但可能引发路由匹配异常,建议统一格式。

解决步骤

  1. 修改useEffect逻辑:只在登录状态从未登录变为已登录时执行导航,而非每次状态变化都触发:
useEffect(() => {
  // 仅在登录状态切换为已登录时,导航到clinic页面
  if (IsLoggedIn) {
    navigate("/clinic", { replace: true });
  }
}, [navigate, IsLoggedIn]);

添加{ replace: true }是为了避免登录后点击返回按钮回到登录页,优化体验。

  1. 修正Router.jsx的路由链接:去掉/clinic/mytasks/末尾的斜杠,保持链接格式一致:
<Link to="/clinic">Message</Link>
<Link to="/clinic/mytasks"> My Tasks </Link>
<Link to="/clinic/members"> Members </Link>
<Link to="/clinic/calendar"> Calendar </Link>
<Outlet />
  1. 优化嵌套路由兜底规则:嵌套路由里的path="*"不要直接跳转到/,改为跳转到当前嵌套路由的首页,避免用户在子路由误输路径直接回到登录页:
// 将嵌套路由中的兜底路由修改为
<Route path="*" element={<Navigate to="/clinic" />} />

这样修改后,点击菜单进入子路由时,useEffect不会再强制导航回根目录,页面就能正常停留在对应子路由组件中了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:50:25