Вот кодыпесочница, который иллюстрирует проблему:
Если у меня есть дерево таких объектов:
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: [] }] }
]
}
];
Я хотел бы иметь возможность ссылаться на такой URL-адрес:
/tasks/2/children/4/children/6.
Пока я могу только получить ссылку на 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 должен быть динамическим, а не конфигурация маршрутов. Конфигурация маршрутов должна быть точкой входа в «корневой» маршрут, отображающий «корневой» компонент TaskPage на "/tasks/:id/*". Компонент 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 с двумя маршрутами: маршрут индекса для отображения ссылок для текущей глубины и маршрут для отображения вложенных дочерних элементов.
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>
);
}
Обратите внимание на подстановочный знак "*" в конце, чтобы разрешить сопоставление вложенных маршрутов.
Также обратите внимание, что обратная ссылка теперь "../..", так как каждый уровень вложенности выдвигает два сегмента пути, поэтому, чтобы вернуться «назад», необходимо удалить два сегмента пути.
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: [] }] }
]
}
];
Когда маршрут является индексным маршрутом, он также не должен использовать опору
path, так как понимается, что путь — это путь обертывающего родительского маршрута макета. Можете ли вы уточнить, что в песочнице конкретно воспроизводит проблему, которую вы пытаетесь решить?