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