Табы и стеки

В React Router концепции табы (Tabs) и стеки (Stacks) служат для управления навигацией на разных уровнях приложения. Они позволяют структурировать интерфейс так, чтобы пользователь мог быстро переключаться между разделами, сохраняя состояние предыдущих экранов.


Стековая навигация (Stack Navigation)

Stack Navigation — это способ организации маршрутов, при котором новые страницы накладываются поверх предыдущих, а возврат происходит путем снятия верхнего элемента стека. Такой подход идеально подходит для сценариев, где пользователь перемещается по иерархии страниц.

Пример базовой структуры стека с React Router:

import { BrowserRouter, Routes, Route, useNavigate } from 'react-router-dom';

function Home() {
  const navigate = useNavigate();
  return (
    <div>
      <h2>Главная</h2>
      <button onCl ick={() => navigate('/profile')}>Перейти в профиль</button>
    </div>
  );
}

function Profile() {
  const navigate = useNavigate();
  return (
    <div>
      <h2>Профиль</h2>
      <button onCl ick={() => navigate(-1)}>Назад</button>
    </div>
  );
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/profile" element={<Profile />} />
      </Routes>
    </BrowserRouter>
  );
}

Ключевые моменты:

  • useNavigate() позволяет управлять переходами программно, включая возврат на предыдущий экран (navigate(-1)).
  • Каждый новый маршрут добавляется в стек браузера, сохраняя историю навигации.

Табовая навигация (Tab Navigation)

Tab Navigation используется для параллельных разделов интерфейса, где пользователь может мгновенно переключаться между вкладками, сохраняя состояние каждой из них. React Router обеспечивает такой функционал через вложенные маршруты и компонент Outlet.

Пример табов:

import { BrowserRouter, Routes, Route, NavLink, Outlet } from 'react-router-dom';

function TabsLayout() {
  return (
    <div>
      <nav>
        <NavLink to="tab1" style={({ isActive }) => ({ fontWeight: isActive ? 'bold' : 'normal' })}>
          Вкладка 1
        </NavLink>
        <NavLink to="tab2" style={({ isActive }) => ({ fontWeight: isActive ? 'bold' : 'normal' })}>
          Вкладка 2
        </NavLink>
      </nav>
      <Outlet />
    </div>
  );
}

function Tab1() {
  return <div>Содержимое вкладки 1</div>;
}

function Tab2() {
  return <div>Содержимое вкладки 2</div>;
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<TabsLayout />}>
          <Route path="tab1" element={<Tab1 />} />
          <Route path="tab2" element={<Tab2 />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

Особенности табов:

  • Использование Outlet позволяет отображать содержимое текущей активной вкладки без перезагрузки всего интерфейса.
  • NavLink предоставляет автоматическое определение активного маршрута и возможность динамически менять стили.
  • Каждая вкладка может содержать вложенные маршруты и собственную стековую навигацию.

Комбинация стеков и табов

Для сложных приложений часто требуется гибридная навигация, где верхний уровень представлен табами, а внутри каждой вкладки реализован стек. Такой подход обеспечивает удобство переключения между разделами и сохранение истории переходов внутри каждой вкладки.

Пример комбинированной структуры:

function Tab1Stack() {
  const navigate = useNavigate();
  return (
    <Routes>
      <Route path="/" element={<div>Главная вкладки 1<button onCl ick={() => navigate('detail')}>Детали</button></div>} />
      <Route path="detail" element={<div>Детали вкладки 1<button onCl ick={() => navigate(-1)}>Назад</button></div>} />
    </Routes>
  );
}

function TabsLayout() {
  return (
    <div>
      <nav>
        <NavLink to="tab1">Вкладка 1</NavLink>
        <NavLink to="tab2">Вкладка 2</NavLink>
      </nav>
      <Outlet />
    </div>
  );
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<TabsLayout />}>
          <Route path="tab1/*" element={<Tab1Stack />} />
          <Route path="tab2" element={<div>Содержимое вкладки 2</div>} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

Особенности комбинирования:

  • Каждая вкладка может содержать собственный стек маршрутов.
  • История навигации внутри вкладки сохраняется при переходе между вкладками.
  • Обеспечивается максимальная гибкость интерфейса без усложнения структуры приложения.

Практические советы

  • Для простых интерфейсов достаточно только табов или стека.
  • Для многоуровневых приложений рекомендуется гибридная модель с вложенными маршрутами.
  • Использование NavLink обеспечивает корректное управление состоянием активной вкладки.
  • Outlet является ключевым компонентом для организации вложенных маршрутов и отображения текущего контента.
  • При работе со стековой навигацией важно помнить о корректной работе navigate(-1) для возврата на предыдущий экран.

Эта структура позволяет создавать масштабируемые и логически упорядоченные приложения, обеспечивая плавную навигацию и сохранение состояния между экранами.