Активные ссылки и стилизация

В React Router управление навигацией осуществляется через компоненты <Link> и <NavLink>. Основное отличие между ними заключается в возможности <NavLink> автоматически определять, какая ссылка активна в текущий момент, и применять специальные стили или классы для активного состояния.

Компонент <NavLink> расширяет функциональность <Link> добавлением пропсов activeClassName и activeStyle (в версии React Router 6 и выше используется функция className или style, зависящая от состояния). Это позволяет динамически изменять внешний вид ссылок в зависимости от текущего маршрута.

Пример использования в React Router v6:

import { NavLink } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <NavLink 
        to="/" 
        className={({ isActive }) => isActive ? 'active-link' : 'inactive-link'}
      >
        Главная
      </NavLink>
      <NavLink 
        to="/about" 
        className={({ isActive }) => isActive ? 'active-link' : 'inactive-link'}
      >
        О нас
      </NavLink>
    </nav>
  );
}

Здесь ключевой момент — использование функции для className, принимающей объект с полем isActive. Когда маршрут совпадает с to, isActive становится true, и ссылка получает указанный класс.

Динамическая стилизация через style

Помимо классов, можно применять инлайн-стили:

<NavLink
  to="/contact"
  style={({ isActive }) => ({
    color: isActive ? 'white' : 'gray',
    backgroundColor: isActive ? 'blue' : 'transparent',
    padding: '8px 12px',
    borderRadius: '4px',
    textDecoration: 'none'
  })}
>
  Контакты
</NavLink>

Такой подход позволяет полностью контролировать визуальное представление активной ссылки без необходимости писать отдельные CSS-классы.

Управление активными ссылками с вложенными маршрутами

Когда маршруты вложенные, React Router по умолчанию считает ссылку активной только при точном совпадении. Для включения активации при частичном совпадении используется проп end:

<NavLink 
  to="/products" 
  end
  className={({ isActive }) => isActive ? 'active-link' : ''}
>
  Продукты
</NavLink>

Без end ссылка /products будет активна также для /products/123 или /products/new. Добавление end заставляет компонент быть активным только при точном совпадении пути.

Составные и вложенные ссылки

При сложной навигационной структуре с вложенными маршрутами <NavLink> сохраняет способность определять активность как для родительских, так и для дочерних ссылок. Пример:

<NavLink 
  to="/dashboard" 
  className={({ isActive }) => isActive ? 'active-parent' : ''}
>
  Панель
</NavLink>
<NavLink 
  to="/dashboard/settings" 
  className={({ isActive }) => isActive ? 'active-child' : ''}
>
  Настройки
</NavLink>

Активность родительской ссылки можно отслеживать через проверку isActive, или использовать специальные селекторы CSS для стилизации дочерних элементов.

Пользовательские функции для вычисления активного состояния

Иногда требуется более сложная логика для определения активности, например, когда маршруты включают параметры или query-параметры. В таких случаях можно использовать хук useMatch или useLocation для вычисления соответствия вручную:

import { useLocation, Link } from 'react-router-dom';

function CustomLink({ to, children }) {
  const location = useLocation();
  const isActive = location.pathname.startsWith(to);

  return (
    <Link 
      to={to} 
      style={{
        color: isActive ? 'red' : 'black',
        fontWeight: isActive ? 'bold' : 'normal'
      }}
    >
      {children}
    </Link>
  );
}

Этот подход полезен, когда нужно учитывать не только путь, но и дополнительные условия, например, query-параметры или состояние приложения.

Рекомендации по стилизации активных ссылок

  • Использовать классы (className) для глобальной стилизации и повторного применения CSS.
  • Применять инлайн-стили (style) для локальных изменений или динамических вычислений.
  • Добавлять проп end для точного совпадения маршрутов.
  • При вложенных маршрутах проверять, нужно ли активировать родительскую ссылку для всех дочерних путей.
  • При сложной логике активных ссылок использовать хук useLocation или useMatch.

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