如何在 react-router v6 的树结构中创建深层路径
how to create deep paths in a tree structure in react-router v6
这里有一个 codesandbox 可以说明问题:
如果我有一棵这样的对象树:
const tasks: Task[] = [
{
id: 1,
name: "one",
children: [
{
id: 3,
name: "three",
children: [{ id: 5, name: "five", children: [] }]
}
]
},
{
id: 2,
name: "two",
children: [
{ id: 4, name: "four", children: [{ id: 6, name: "six", children: [] }] }
]
}
];
我希望能够 link 变成 url 这样的:
/tasks/2/children/4/children/6
.
到目前为止,我只能通过以下路线结构将其到达 link 到 tasks/2/children/6
:
let routes: RouteObject[] = [
{
path: "tasks",
element: <Layout />,
children: [
{
path: ":id",
element: <TaskPage />,
children: [
{ path: "children/:id", element: <TaskPage />, index: true }
]
},
{
index: true,
element: <TaskTreePage />
}
]
},
{
index: true,
element: <Navigate to="tasks" />
}
];
let element = useRoutes(routes);
每次进入新的深度时,我都需要不断添加嵌套路线。
有没有一种方法可以动态构建适用于任何深度的深层嵌套路由路径?
当路由是索引路由时,它不应该也使用 path
属性,因为它理解路径是包装父布局路由的路径。
TaskPage
组件应该是动态的,而不是路由配置。路由配置应该是在 "/tasks/:id/*"
上呈现“根”TaskPage
组件的“根”路由的入口点。 TaskPage
组件现在有效地递归地在它呈现的新嵌套相对路由 <Route path="children/:id/*" element={<TaskPage />} />
中呈现自身的另一个实例。
代码示例:
应用程序
const routes: RouteObject[] = [
{
path: "/tasks",
element: <Layout />,
children: [
{
path: ":id/*",
element: <TaskPage />
},
{
index: true,
element: <TaskTreePage />
}
]
},
{
index: true,
element: <Navigate to="/tasks" />
}
];
export default function App() {
const element = useRoutes(routes);
return element;
}
任务页面
这就是“魔法”发生的地方。它渲染了一个新的 Routes
组件,其中包含两条路由,一条索引路由用于渲染当前深度的 links 和一条渲染嵌套子级的路由。
function TaskPage() {
const { id } = useParams();
const task = findTask(id as string, tasks);
if (!task) {
return <h2>Not Found!</h2>;
}
return (
<Routes>
<Route
index
element={
<div>
<h2>task of {task.name}</h2>
<div>
<Link to="../..">Back</Link>
<div>
<h2>Children</h2>
{task.children.map((child: Task) => (
<Link key={child.id} to={`children/${child.id}`}>
{child.name}
</Link>
))}
</div>
</div>
</div>
}
/>
<Route path="children/:id/*" element={<TaskPage />} />
</Routes>
);
}
注意尾随通配符 "*"
匹配器以允许匹配嵌套路由。
另请注意,后面的 link 现在是 "../.."
,因为每一层嵌套都会推动两个路径段,因此要“返回”两个路径段需要删除。
const tasks: Task[] = [
{
id: 1,
name: "one",
children: [
{
id: 3,
name: "three",
children: [
{
id: 5,
name: "five",
children: [{ id: 7, name: "seven", children: [] }]
}
]
}
]
},
{
id: 2,
name: "two",
children: [
{ id: 4, name: "four", children: [{ id: 6, name: "six", children: [] }] }
]
}
];
这里有一个 codesandbox 可以说明问题:
如果我有一棵这样的对象树:
const tasks: Task[] = [
{
id: 1,
name: "one",
children: [
{
id: 3,
name: "three",
children: [{ id: 5, name: "five", children: [] }]
}
]
},
{
id: 2,
name: "two",
children: [
{ id: 4, name: "four", children: [{ id: 6, name: "six", children: [] }] }
]
}
];
我希望能够 link 变成 url 这样的:
/tasks/2/children/4/children/6
.
到目前为止,我只能通过以下路线结构将其到达 link 到 tasks/2/children/6
:
let routes: RouteObject[] = [
{
path: "tasks",
element: <Layout />,
children: [
{
path: ":id",
element: <TaskPage />,
children: [
{ path: "children/:id", element: <TaskPage />, index: true }
]
},
{
index: true,
element: <TaskTreePage />
}
]
},
{
index: true,
element: <Navigate to="tasks" />
}
];
let element = useRoutes(routes);
每次进入新的深度时,我都需要不断添加嵌套路线。
有没有一种方法可以动态构建适用于任何深度的深层嵌套路由路径?
当路由是索引路由时,它不应该也使用 path
属性,因为它理解路径是包装父布局路由的路径。
TaskPage
组件应该是动态的,而不是路由配置。路由配置应该是在 "/tasks/:id/*"
上呈现“根”TaskPage
组件的“根”路由的入口点。 TaskPage
组件现在有效地递归地在它呈现的新嵌套相对路由 <Route path="children/:id/*" element={<TaskPage />} />
中呈现自身的另一个实例。
代码示例:
应用程序
const routes: RouteObject[] = [
{
path: "/tasks",
element: <Layout />,
children: [
{
path: ":id/*",
element: <TaskPage />
},
{
index: true,
element: <TaskTreePage />
}
]
},
{
index: true,
element: <Navigate to="/tasks" />
}
];
export default function App() {
const element = useRoutes(routes);
return element;
}
任务页面
这就是“魔法”发生的地方。它渲染了一个新的 Routes
组件,其中包含两条路由,一条索引路由用于渲染当前深度的 links 和一条渲染嵌套子级的路由。
function TaskPage() {
const { id } = useParams();
const task = findTask(id as string, tasks);
if (!task) {
return <h2>Not Found!</h2>;
}
return (
<Routes>
<Route
index
element={
<div>
<h2>task of {task.name}</h2>
<div>
<Link to="../..">Back</Link>
<div>
<h2>Children</h2>
{task.children.map((child: Task) => (
<Link key={child.id} to={`children/${child.id}`}>
{child.name}
</Link>
))}
</div>
</div>
</div>
}
/>
<Route path="children/:id/*" element={<TaskPage />} />
</Routes>
);
}
注意尾随通配符 "*"
匹配器以允许匹配嵌套路由。
另请注意,后面的 link 现在是 "../.."
,因为每一层嵌套都会推动两个路径段,因此要“返回”两个路径段需要删除。
const tasks: Task[] = [
{
id: 1,
name: "one",
children: [
{
id: 3,
name: "three",
children: [
{
id: 5,
name: "five",
children: [{ id: 7, name: "seven", children: [] }]
}
]
}
]
},
{
id: 2,
name: "two",
children: [
{ id: 4, name: "four", children: [{ id: 6, name: "six", children: [] }] }
]
}
];