Стилизация активных ссылок

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


Основной способ создания навигации в TanStack Router — это компонент <Link>. Он принимает to — путь маршрута, на который ведет ссылка, и может использоваться вместе с функцией className или style для динамической стилизации.

import { Link, useMatch } from '@tanstack/router';

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

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


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

Помимо классов, можно напрямую изменять inline-стили ссылки на основе состояния активности:

<Link
  to="/profile"
  style={({ isActive }) => ({
    color: isActive ? 'white' : 'gray',
    fontWeight: isActive ? 'bold' : 'normal',
    textDecoration: isActive ? 'underline' : 'none'
  })}
>
  Профиль
</Link>

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


Составные маршруты и активность

TanStack Router поддерживает вложенные маршруты. Важно учитывать, что активность ссылки может проверяться как на точное совпадение пути, так и с учетом дочерних маршрутов. Для этого используется параметр end:

<Link
  to="/dashboard"
  className={({ isActive }) => isActive ? 'active-link' : ''}
  end
>
  Панель
</Link>

Если end={true}, ссылка считается активной только при точном совпадении пути /dashboard. Без end ссылка будет активной для любого пути, который начинается с /dashboard, например /dashboard/settings.


Применение с кастомными компонентами

Иногда требуется обернуть <Link> в кастомный компонент. В этом случае useMatch позволяет вручную определить активность:

import { useMatch, useRouter } from '@tanstack/router';

function CustomNavLink({ to, children }) {
  const match = useMatch(to);
  const isActive = Boolean(match);

  return (
    <a href={to} className={isActive ? 'active-link' : 'inactive-link'}>
      {children}
    </a>
  );
}

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


Советы по организации стилей

  1. Разделение состояния и оформления: лучше создавать отдельные CSS-классы (active-link, inactive-link) вместо inline-стилей для поддержки масштабируемости.
  2. Псевдоклассы и transitions: использование :hover, :focus и плавных переходов улучшает пользовательский опыт.
  3. Вложенные маршруты: всегда учитывать, нужно ли подсвечивать родительскую ссылку при активном дочернем маршруте.

Пример комплексной навигации

<nav>
  <Link 
    to="/home" 
    className={({ isActive }) => isActive ? 'nav-item active' : 'nav-item'}
  >
    Главная
  </Link>
  <Link 
    to="/dashboard" 
    className={({ isActive }) => isActive ? 'nav-item active' : 'nav-item'}
    end
  >
    Панель
  </Link>
  <Link 
    to="/settings/profile" 
    className={({ isActive }) => isActive ? 'nav-item active' : 'nav-item'}
  >
    Настройки
  </Link>
</nav>

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


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