Гид по технологиям

Создание сайдбар-навигации в React с Material UI и react-router

6 min read React Обновлено 18 Dec 2025
React сайдбар с Material UI и react-router
React сайдбар с Material UI и react-router

TL;DR

Коротко: пошаговое руководство по созданию горизонтально-фиксированного сайдбара в React, который содержит ссылки с иконками Material UI и маршрутизацию через react-router-dom. Включены готовые примеры кода для navData, Sidenav, CSS-модуля, конфигурации роутов и советы по доступности, тестированию и оптимизации.

Введение

Крупный план руки, держащей аналоговый компас

Сайдбар (боковая навигация) — это вертикальный список ссылок, часто с иконками. В React такой компонент удобно собрать из массива данных и отрисовать через map. В этом руководстве вы создадите коллапсируемый сайдбар со сменой иконки, локально-скоупед CSS-модулями и маршрутизацией через react-router-dom.

Важно: если у вас уже есть проект React, пропустите раздел о создании приложения и переходите к компонентам.

Что вы получите

  • Коллапсируемый сайдбар с иконками Material UI
  • Маршрутизация через react-router-dom (NavLink)
  • Локальные стили через CSS Modules
  • Проверки доступности и короткий план тестирования

Основные термины

  • NavLink: компонент из react-router-dom для ссылок, которые знают активный маршрут.
  • CSS Modules: способ писать локально-скоупед CSS-классы в React.
  • Коллапс/разворачивание: изменение ширины сайдбара и видимости текста.

1. Создание React-приложения

Если проекта нет, создайте быстрый шаблон при помощи create-react-app:

npx create-react-app react-sidenav

Это создаст папку react-sidenav с преднастроенной сборкой и зависимостями. Чтобы упростить стартовую структуру, откройте src/App.js и замените содержимое на базовый шаблон:

import './App.css';

function App() {
  return (
    
); } export default App;

2. Структура проекта (рекомендуемая)

Пример дерева файлов проекта, которое мы будем использовать:

  • src/
    • Components/
      • Sidenav.js
      • sidenav.module.css
    • Pages/
      • Home.js
      • Explore.js
      • Statistics.js
      • Settings.js
    • lib/
      • navData.js
    • App.js
    • index.js

Эта структура разделяет логику навигации, страницу и данные навигации.

3. Данные навигации (navData)

Создайте папку lib и файл navData.js. В нем хранится массив объектов с иконкой, текстом и ссылкой.

import HomeIcon from '@mui/icons-material/Home';
import TravelExploreIcon from '@mui/icons-material/TravelExplore';
import BarChartIcon from '@mui/icons-material/BarChart';
import SettingsIcon from '@mui/icons-material/Settings';

export const navData = [
    {
        id: 0,
        icon: ,
        text: "Home",
        link: "/"
    },
    {
        id: 1,
        icon: ,
        text: "Explore",
        link: "explore"
    },
    {
        id: 2,
        icon: ,
        text: "Statistics",
        link: "statistics"
    },
    {
        id: 3,
        icon: ,
        text: "Settings",
        link: "settings"
    }
]

Убедитесь, что установили Material UI и иконки:

npm install @mui/material @emotion/react @emotion/styled
npm install @mui/icons-material

4. Компонент Sidenav

В папке Components создайте Sidenav.js. Компонент читает navData и рендерит элементы через NavLink. Полный пример Sidenav с коллапсом и переключателем состояния:

// In Sidenav.js
import React, { useState } from 'react';
import { NavLink } from 'react-router-dom';
import { navData } from "../lib/navData";
import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft';
import KeyboardDoubleArrowRightIcon from '@mui/icons-material/KeyboardDoubleArrowRight';
import styles from './sidenav.module.css';

export default function Sidenav() {
  const [open, setOpen] = useState(true);

  const toggleOpen = () => {
    setOpen(!open);
  }

  return (
    
{navData.map(item => { return ( {item.icon} {item.text} ) })}
) }

Примечание: в react-router-dom v6 у NavLink проп activeClassName заменён на стиль-пропс или функцию; в примере выше используется activeclassname для краткости — в вашем проекте замените на правильный синтаксис (см. советы по совместимости ниже).

5. CSS-модуль (sidenav.module.css)

Пример локальных стилей для сайдбара (в папке Components создайте sidenav.module.css):

.sidenav {
    width: 250px;
    transition: width 0.3s ease-in-out;
    height: 100vh;
    background-color: rgb(10,25,41);
    padding-top: 28px;
}

.sidenavClosed {
    composes: sidenav;
    transition: width 0.3s ease-in-out;
    width: 60px
}

.sideitem {
    display: flex;
    align-items: center;
    padding: 10px 20px;
    cursor: pointer;
    color: #B2BAC2;
    text-decoration: none;
}

.linkText {
    padding-left: 16px;
}

.linkTextClosed {
    composes: linkText;
    visibility: hidden;
}

.sideitem:hover {
    background-color: #244f7d1c;

}

.menuBtn {
    align-self: center;
    align-self: flex-start;    
    justify-self: flex-end;
    color: #B2BAC2;
    background-color: transparent;
    border: none;
    cursor: pointer;
    padding-left: 20px;
}

Совет: при использовании CSS Modules имена классов локализуются, что предотвращает конфликты.

6. Маршрутизация с react-router-dom

Установите пакет:

npm install react-router-dom@latest

В index.js оберните приложение BrowserRouter:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  
    
      
    
  
);

В App.js настройте маршруты и включите Sidenav:

import './App.css';
import Sidenav from './Components/Sidenav';
import Explore from "./Pages/Explore";
import Home from "./Pages/Home";
import Settings from "./Pages/Settings";
import Statistics from "./Pages/Statistics";
import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    
}/> } /> }/> } />
); } export default App;

Обновите App.css, чтобы главный контейнер использовал flex:

body {
  margin: 0;
  padding: 0;
}

.App {
  display: flex;
}

main {
  padding: 10px;
}

7. Примеры страниц

Добавьте простые компоненты в папку Pages:

// Home.js
export default function Home() {
  return (
    
Home
) }

То же для Explore, Statistics и Settings. После запуска приложения переходы по ссылкам в сайдбаре должны менять содержимое main.

8. Модификация ссылок: NavLink vs div

Если в Sidenav вы рендерили div-элементы, замените их на NavLink, чтобы получить ссылку и подсветку активного маршрута. Пример внутри map:

{navData.map(item => {
    return 
               {item.icon}
               {item.text}
           
})}

Обратите внимание на prop to — он принимает относительный или абсолютный путь.

9. Доступность и ARIA

  • Кнопке toggle добавьте aria-label и aria-expanded. Это помогает экранным читалкам.
  • Убедитесь, что контраст текста и фона отвечает требованиям WCAG (контраст должен быть достаточным для чтения).
  • Навигацию можно обернуть в элемент

10. Тестирование и критерии приёмки

Критерии приёмки:

  • Сайдбар по умолчанию открыт при загрузке (open === true).
  • По клику на кнопку сайдбар сворачивается/разворачивается, меняется иконка.
  • Навигация меняет путь и отображаемую страницу при клике.
  • Активный маршрут подсвечивается стилем.
  • Сайдбар доступен с клавиатуры (tab, enter).

Минимальные тест-кейсы:

  • Навигация: клик по каждой ссылке ведёт на соответствующую страницу.
  • Коллапс: при клике на кнопку ширина изменяется, текст скрывается, иконка меняется.
  • Accessibility: aria-атрибуты присутствуют и работают с экранными читалками.

11. Альтернативные подходы

  • CSS-in-JS (styled-components / @emotion): если вы предпочитаете JS-стили, можно вынести стили в компоненты.
  • Использовать Drawer из Material UI вместо самописного сайдбара — проще интегрируется с темами MUI.
  • Для сложных приложений с ролями: генерируйте navData на основе прав пользователя.

12. Когда этот подход не подходит

  • Если вам нужен overlay-дашборд на мобильных устройствах, лучше использовать MUI Drawer или адаптивный компонент, который перекрывает контент.
  • Для очень больших проектов с динамической навигацией из бека стоит хранить конфигурацию на сервере и мапить её на UI.

13. Подсказки по производительности

  • Не храните JSX-иконки внутри navData как результат выражений, если navData приходит из API. Лучше хранить ключ и мапить ключ в компонент иконки при рендере.
  • Отдельные страницы загружайте лениво (React.lazy + Suspense), чтобы не тянуть весь код страниц при первом рендере.

14. Совместимость и миграция

  • Для react-router-dom v6 используйте и element={} вместо .
  • Проверяйте API NavLink: для динамического активного класса используйте функцию className: className={({ isActive }) => isActive ? styles.active : styles.sideitem}

15. Рекомендации по UX

  • Для маленьких экранов замените сайдбар на скрываемый Drawer.
  • Показывайте подсказку (tooltip) при наведении на иконку в свернутом состоянии, чтобы пользователь видел название ссылки.
  • Добавьте плавные переходы для ширины и видимости текста для лучшего ощущения.

16. Чеклист для ролей

Для разработчика:

  • Установлены зависимости MUI и react-router-dom
  • Создан navData и Sidenav
  • Реализован коллапс и aria-атрибуты
  • Добавлены тесты навигации

Для дизайнера:

  • Проверен контраст иконок и текста
  • Подтверждён поведение в свернутом и развёрнутом виде

Для QA:

  • Пройдены тест-кейсы маршрутизации и клавиатурной навигации
  • Проверено поведение на мобильных устройствах

17. Проблемы и отладка

  • Иконки не отображаются: убедитесь, что вы установили @mui/icons-material и импортируете нужные компоненты.
  • NavLink не подсвечивается: в v6 используйте className={({ isActive }) => isActive ? styles.active : styles.sideitem}.
  • CSS-модули не работают: проверьте расширение файла .module.css и корректный импорт styles from ‘./sidenav.module.css’.

18. Пример готовой реализации (сводка файлов)

  • src/lib/navData.js — массив объектов навигации с иконками
  • src/Components/Sidenav.js — основной компонент сайдбара
  • src/Components/sidenav.module.css — локальные стили
  • src/Pages/* — простые компоненты страниц
  • src/App.js и src/index.js — маршрутизация и обёртка BrowserRouter

Если нужно, вы можете клонировать репозиторий с готовым примером (поиск на GitHub по ключевым словам: react sidenav material-ui).

19. Итог

React делает создание коллапсируемого сайдбара простым: используйте массив данных для пунктов, NavLink для маршрутов, useState для управления состоянием «открыто/закрыто» и CSS Modules для локальных стилей. В продакшн-версии добавьте ARIA-атрибуты, ленивую загрузку страниц и адаптивность для мобильных устройств.

Важно: адаптируйте подход в зависимости от размеров проекта и требуемой гибкости — от простого самописного сайдбара до использования готовых компонентов, таких как Drawer из Material UI.

Краткое резюме

  • Храните navData отдельно и мапьте на NavLink.
  • Управляйте коллапсом через useState и переключатель.
  • Используйте react-router-dom v6 API (Routes/Route/NavLink).
  • Улучшайте UX подсказками и доступностью.

Примечания

Вид навигационного меню React в развернутом виде

Свернутое навигационное меню React

Если вам нужен полный рабочий проект с настройками ESLint, Prettier и готовыми тестами, дайте знать — могу добавить пример конфигурации и шаблоны тестов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство