TanStack Router предоставляет мощный механизм для организации маршрутов с использованием вложенных layouts, что позволяет создавать сложные интерфейсы с разделением логики отображения и маршрутизации. Основная идея заключается в том, что каждый layout может оборачивать дочерние маршруты, предоставляя общий контекст, стили или функциональность.
Layout — это компонент, который не привязан к конкретному URL, а
служит оберткой для группы маршрутов. В TanStack Router layout
определяется аналогично обычному маршруту, но вместо
component обычно используется element или
loader, чтобы обернуть дочерние маршруты. Пример базовой
структуры:
import { createRouter, Route } from '@tanstack/router';
import AppLayout from './layouts/AppLayout';
import Dashboard from './pages/Dashboard';
import Settings from './pages/Settings';
const router = createRouter({
routeTree: new Route({
path: '/',
element: <AppLayout />, // Основной layout
children: [
new Route({ path: 'dashboard', element: <Dashboard /> }),
new Route({ path: 'settings', element: <Settings /> }),
],
}),
});
В этом примере AppLayout является корневым layout,
который оборачивает все дочерние страницы, предоставляя общую навигацию
или структуру.
Вложенные layouts позволяют создавать иерархическую структуру интерфейса, где каждый уровень маршрутизации может добавлять свою обертку. Основные преимущества:
Пример вложенных layouts:
const router = createRouter({
routeTree: new Route({
path: '/',
element: <AppLayout />,
children: [
new Route({
path: 'dashboard',
element: <DashboardLayout />,
children: [
new Route({ path: 'analytics', element: <AnalyticsPage /> }),
new Route({ path: 'reports', element: <ReportsPage /> }),
],
}),
new Route({ path: 'settings', element: <Settings /> }),
],
}),
});
Здесь DashboardLayout оборачивает только дочерние
страницы analytics и reports, сохраняя
отдельную структуру от главного AppLayout.
outletДля отображения дочерних маршрутов внутри layout используется
компонент Outlet. Он служит как место вставки
дочернего контента:
import { Outlet } from '@tanstack/router';
function DashboardLayout() {
return (
<div className="dashboard-layout">
<Sidebar />
<main>
<Outlet /> {/* Здесь будут отображаться дочерние маршруты */}
</main>
</div>
);
}
Outlet автоматически рендерит активный дочерний маршрут,
сохраняя структуру родительского layout.
Layouts могут включать загрузчики данных
(loader) и передавать контекст в дочерние маршруты. Это
особенно полезно для авторизации, получения данных пользователя или
настройки темы:
const router = createRouter({
routeTree: new Route({
path: '/',
element: <AppLayout />,
loader: async () => {
const user = await fetchUser();
return { user };
},
children: [
new Route({
path: 'dashboard',
element: <DashboardLayout />,
loader: async ({ parentData }) => {
const { user } = parentData;
const projects = await fetchProjects(user.id);
return { projects };
},
children: [
new Route({ path: 'analytics', element: <AnalyticsPage /> }),
],
}),
],
}),
});
В этом примере дочерний layout получает данные родителя через
parentData, что упрощает передачу информации между уровнями
маршрутизации.
Используя вложенные layouts, можно создавать плавные анимации переходов между страницами, не перезагружая весь интерфейс. Поскольку каждый layout рендерит только свою часть, дочерние компоненты могут изменяться независимо, позволяя использовать:
main части layoutOutletimport { motion } from 'framer-motion';
import { Outlet } from '@tanstack/router';
function DashboardLayout() {
return (
<div className="dashboard-layout">
<Sidebar />
<motion.main initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
<Outlet />
</motion.main>
</div>
);
}
TanStack Router поддерживает динамические сегменты URL внутри layouts. Это позволяет создавать многоуровневую маршрутизацию с параметрами:
new Route({
path: 'projects/:projectId',
element: <ProjectLayout />,
children: [
new Route({ path: 'overview', element: <ProjectOverview /> }),
new Route({ path: 'tasks', element: <ProjectTasks /> }),
],
});
ProjectLayout может использовать useParams
для получения projectId и предоставления данных всем
дочерним маршрутам через контекст.
Вложенные layouts в TanStack Router обеспечивают структурированную, масштабируемую и модульную маршрутизацию, позволяя создавать интерфейсы с общей и индивидуальной логикой для разных разделов приложения.