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

React路由报错:<Routes>子组件必须为<Route>,侧边栏需排除/login路由

问题解决:修复React Router嵌套路由报错并实现SideBar路由隐藏

报错原因分析

你遇到的[Routes] is not a <Route> component. All component children of <Routes> must be a <Route>错误,是因为React Router v6不允许在<Route>的子节点直接放置<Routes>,嵌套路由需要通过<Outlet>组件实现。同时你的代码混合了v5和v6的路由写法(比如旧版<Route>直接包裹内容而非使用element属性),导致逻辑混乱。

核心解决方案

  1. 统一React Router v6写法:所有路由必须包裹在<Routes>内,使用element属性指定渲染组件,移除v5风格的<Route>写法。
  2. 修复嵌套路由结构:受保护路由(ProtectedRoutes)内部通过<Outlet>渲染子路由,而非嵌套<Routes>。
  3. 条件渲染SideBar:通过useLocation获取当前路径,仅当路径不是/login时渲染侧边栏。

修改后的代码示例

1. App.js 重构

import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
import { useState } from 'react';
import SideBar from './SideBar';
import Login from './Login';
import ProtectedRoutes from './ProtectedRoutes';
import Main from './Main';

function App() {
  const [inactive, setInactive] = useState(false);
  const location = useLocation();

  // 判断是否需要显示SideBar
  const showSideBar = location.pathname !== '/login';

  return (
    <Router>
      <div className="App">
        {/* 条件渲染SideBar */}
        {showSideBar && (
          <SideBar
            onCollapse={(inactive) => {
              console.log(inactive);
              setInactive(inactive);
            }}
          />
        )}
        <div className={`container ${inactive ? "inactive" : ""}`}>
          <Routes>
            {/* 登录路由,不显示SideBar */}
            <Route path="/login" element={<Login />} />
            
            {/* 受保护的路由组,需要验证权限 */}
            <Route path="/" element={<ProtectedRoutes />}>
              {/* 子路由通过Outlet渲染 */}
              <Route index element={<h1>Dashboard</h1>} />
              <Route path="main" element={<Main />} />
              <Route path="content" element={<h1>Content</h1>}>
                <Route path="courses" element={<h1>Courses</h1>} />
                <Route path="videos" element={<h1>Videos</h1>} />
              </Route>
              <Route path="design" element={<h1>Design</h1>} />
              <Route path="content-2" element={<h1>Content 2</h1>}>
                <Route path="courses" element={<h1>Courses</h1>} />
                <Route path="videos" element={<h1>Videos</h1>} />
              </Route>
              <Route path="design-2" element={<h1>Design 2</h1>} />
              <Route path="design-3" element={<h1>Design 3</h1>} />
              <Route path="design-4" element={<h1>Design 4</h1>} />
            </Route>
          </Routes>
        </div>
      </div>
    </Router>
  );
}

export default App;

2. ProtectedRoutes.js 调整

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

function ProtectedRoutes() {
  // 替换为你的实际权限验证逻辑,比如判断用户是否登录
  const isAuthenticated = true;

  return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
}

export default ProtectedRoutes;

3. SideBar组件(补充说明)

你的menuItems可以直接在SideBar组件中生成导航菜单,无需在App.js中零散渲染路由:

import { Link } from 'react-router-dom';
import { menuItems } from './menuItems';

function SideBar({ onCollapse }) {
  return (
    <div className="sidebar">
      {/* 这里添加折叠按钮逻辑 */}
      {menuItems.map(menu => (
        <div key={menu.name} className="menu-item">
          <Link to={menu.to}>{menu.name}</Link>
          {/* 渲染子菜单 */}
          {menu.subMenus && menu.subMenus.length > 0 && (
            <div className="submenu">
              {menu.subMenus.map(subMenu => (
                <Link key={subMenu.name} to={subMenu.to}>{subMenu.name}</Link>
              ))}
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

export default SideBar;

关键注意点

  • React Router v6中exact属性已被移除,路由默认是精准匹配,根路由用index属性指定默认子路由。
  • 所有路由必须放在<Routes>组件内部,不能直接在组件中零散渲染<Route>。
  • 嵌套路由依赖<Outlet>组件作为子路由的占位符,而非嵌套<Routes>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:54:23