Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Макеты и вложенные маршруты

У страниц блога общая шапка и подвал. Чтобы не повторять их в каждом файле, используют макет (layout) — маршрут, который рисует общую часть и оставляет место для вложенной страницы. Это место обозначают компонентом Outlet.

Компонент макета

Создайте файл app/routes/layout.tsx:

// app/routes/layout.tsx
import { Outlet } from "react-router";
 
export default function Layout() {
  return (
    <>
      <header>Мой блог</header>
      <main>
        <Outlet />
      </main>
      <footer>© 2026</footer>
    </>
  );
}

На месте Outlet будет отрисована та вложенная страница, адрес которой открыт сейчас.

Подключение макета

Функция layout(файл, [маршруты]) оборачивает маршруты в макет:

// app/routes.ts
import { type RouteConfig, index, layout, route } from "@react-router/dev/routes";
 
export default [
  layout("routes/layout.tsx", [
    index("routes/home.tsx"),
    route("about", "routes/about.tsx"),
  ]),
] satisfies RouteConfig;

Теперь и /, и /about показываются с шапкой «Мой блог» и подвалом. Сам layout не добавляет ничего к адресу.

Вложенный маршрут с адресом

Если третьим аргументом передать route массив, маршрут станет родителем: его адрес — начало адресов детей, а компонент — макет для них. Индексный маршрут внутри — страница для адреса самого родителя:

// app/routes.ts
route("dashboard", "routes/dashboard.tsx", [
  index("routes/dashboard-home.tsx"),       // /dashboard
  route("stats", "routes/dashboard-stats.tsx"), // /dashboard/stats
]),

В app/routes/dashboard.tsx тоже должен быть Outlet, иначе дочерние страницы не появятся.

Только префикс

Когда нужен общий адрес без общего компонента, используют prefix:

// app/routes.ts
import { prefix, route } from "@react-router/dev/routes";
 
// внутри массива маршрутов:
...prefix("admin", [
  route("posts", "routes/admin-posts.tsx"), // /admin/posts
  route("users", "routes/admin-users.tsx"), // /admin/users
]),

prefix возвращает массив, поэтому его разворачивают оператором ....

Сводка

ФункцияАдресКомпонент
route с детьмиДобавляет часть адресаМакет с Outlet
layoutНе меняетМакет с Outlet
prefixДобавляет часть адресаНет
indexАдрес родителяСтраница

Частая ошибка

Маршруты добавлены внутрь layout, но на странице видна только шапка. Причина почти всегда одна — в компоненте макета забыли <Outlet />. Макет сам решает, где показать дочернюю страницу, и без Outlet она просто не выводится.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.