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

React Router v6如何实现基于数据的Route递归渲染?

问题根因

React Router v6 对路由节点做了强校验:

  • <Routes> 下的直接子元素只能是原生 <Route> 组件或 <React.Fragment>
  • 嵌套 <Route> 的子路由节点也必须符合上述要求

你封装的RecursiveRoute属于自定义函数组件,哪怕内部返回值是<Route>,在React元素树中它的类型标识是RecursiveRoute而非官方要求的Route,因此会直接抛出你看到的错误:

[RecursiveRoute] is not a component. All component children of must be a or <React.Fragment>

可行实现方案

方案1:递归函数直接渲染Route(适配原有逻辑,改造成本最低)

去掉自定义组件包裹层,改用纯递归函数直接返回Route元素树,完全符合React Router的校验规则,支持任意深度嵌套:

import React from "react";
import { BrowserRouter, Routes, Route} from "react-router-dom";
import "./styles.css";

function GenericPage() {
  return <div className="page">Generic page</div>;
}

const nav = {
  slug: "",
  title: "Home",
  children: [
    {
      slug: "foo",
      title: "Foo"
    },
    {
      slug: "bar",
      title: "Bar"
    }
  ]
};

// 递归渲染路由节点,直接返回原生Route元素
const renderRecursiveRoutes = (node) => {
  return (
    <Route path={node.slug} element={<GenericPage />}>
      {node.children?.map((child) => renderRecursiveRoutes(child))}
    </Route>
  );
};

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        {renderRecursiveRoutes(nav)}
      </Routes>
    </BrowserRouter>
  );
}

方案2:使用官方useRoutes钩子(推荐长期维护场景)

React Router v6 原生提供useRoutes配置式路由API,天然支持对象结构的路由配置,不需要手动渲染Route组件,扩展性更强:

import React from "react";
import { BrowserRouter, useRoutes } from "react-router-dom";
import "./styles.css";

function GenericPage() {
  return <div className="page">Generic page</div>;
}

const nav = {
  slug: "",
  title: "Home",
  children: [
    {
      slug: "foo",
      title: "Foo"
    },
    {
      slug: "bar",
      title: "Bar"
    }
  ]
};

// 将业务导航数据转换为useRoutes要求的配置格式
const formatRouteConfig = (node) => {
  return {
    path: node.slug,
    element: <GenericPage />,
    children: node.children?.map(child => formatRouteConfig(child))
  }
};

function AppRoutes() {
  const routeConfig = [formatRouteConfig(nav)];
  return useRoutes(routeConfig);
}

export default function App() {
  return (
    <BrowserRouter>
      <AppRoutes />
    </BrowserRouter>
  );
}

两种方案都可以实现任意深度的递归路由渲染,如果你只是想快速修复原有代码,选方案1即可;如果后续要扩展路由懒加载、权限拦截、索引路由等能力,优先选方案2。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:57:19