Лейауты страниц
Это руководство рассматривает абстракцию лейаута страницы — когда несколько страниц имеют одинаковую структуру, отличаясь только основным содержимым.
Простой лейаут
Заголовок раздела «Простой лейаут»Самый простой лейаут можно увидеть прямо на этой странице. Он имеет хэдер с навигацией по сайту, два сайдбара и футер с внешними ссылками. Здесь нет сложной бизнес-логики, и единственные динамические части — это сайдбары и переключатели справа в хэдере. Такой лейаут можно разместить целиком в shared/ui или в app/layouts, с заполнением контента сайдбаров через пропы:
import { Link, Outlet } from "react-router-dom";import { useThemeSwitcher } from "./useThemeSwitcher";
export function Layout({ siblingPages, headings }) { const [theme, toggleTheme] = useThemeSwitcher();
return ( <div> <header> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/docs">Docs</Link> </li> <li> <Link to="/blog">Blog</Link> </li> </ul> </nav> <button onClick={toggleTheme}>{theme}</button> </header> <main> <SiblingPageSidebar siblingPages={siblingPages} /> <Outlet /> {/* Здесь будет основное содержимое страницы */} <HeadingsSidebar headings={headings} /> </main> <footer> <ul> <li>GitHub</li> <li>Twitter</li> </ul> </footer> </div> );}export function useThemeSwitcher() { const [theme, setTheme] = useState("light");
function toggleTheme() { setTheme(theme === "light" ? "dark" : "light"); }
useEffect(() => { document.body.classList.remove("light", "dark"); document.body.classList.add(theme); }, [theme]);
return [theme, toggleTheme] as const;}Код сайдбаров оставлен читателю в качестве упражнения 😉.
Использование виджетов в лейауте
Заголовок раздела «Использование виджетов в лейауте»Иногда есть необходимость включить в лейаут определенную бизнес-логику, особенно если вы используете глубоко вложенные маршруты с роутером типа React Router. Тогда вы не можете хранить лейаут в Shared или в Widgets из-за правила импорта для слоёв:
Модуль в слайсе может импортировать другие слайсы только в том случае, если они расположены на слоях строго ниже.
Прежде чем обсуждать решения, нам нужно обсудить, действительно ли это проблема. Вам действительно нужен этот лейаут, и если да, действительно ли он должен быть виджетом? Если блок бизнес-логики, про который идёт речь, используется на 2-3 страницах, и лейаут просто является небольшой обёрткой для этого виджета, рассмотрите один из этих двух вариантов:
-
Напишите ваш лейаут прямо в коде роутера на уровне App
Это отлично подходит для роутеров, поддерживающих вложенность, потому что вы можете группировать определенные маршруты и применять нужный лейаут только к ним. -
Просто скопируйте его
Желание абстрагировать код часто переоценено. Это особенно верно для лейаутов, потому что они редко меняются. В какой-то момент, если одна из этих страниц потребует изменений, вы можете просто внести изменения, не затрагивая другие страницы. Если вы беспокоитесь, что кто-то может забыть обновить другие страницы, всегда можно оставить комментарий, описывающий отношения между страницами.
Если ни один из вышеперечисленных вариантов не подходит, есть два решения для включения виджета в лейаут:
-
Используйте render props или слоты
Большинство фреймворков позволяют передавать часть UI внешне. В React это называется render props, в Vue — слоты. -
Переместите лейаут на уровень App
Вы также можете хранить свой лейаут на уровне App, например, вapp/layouts, и комбинировать любые виджеты, которые вам нужны.
Дополнительные материалы
Заголовок раздела «Дополнительные материалы»- Пример создания лейаута с аутентификацией с помощью React и Remix (аналогичен React Router) можно найти в туториале.