Навигация между страницами
В предыдущей главе вы создали макет и страницы панели управления. Теперь давайте добавим несколько ссылок, чтобы пользователи могли перемещаться между маршрутами панели.
Зачем оптимизировать навигацию?
Для перехода между страницами традиционно используется HTML-элемент <a>
. Сейчас ссылки в боковой панели используют элементы <a>
, но обратите внимание, что происходит при переходе между домашней страницей, счетами и страницами клиентов в вашем браузере.
Вы заметили?
При каждом переходе происходит полная перезагрузка страницы!
Компонент <Link>
В Next.js вы можете использовать компонент <Link />
для перехода между страницами вашего приложения. <Link>
позволяет осуществлять клиентскую навигацию с помощью JavaScript.
Чтобы использовать компонент <Link />
, откройте файл /app/ui/dashboard/nav-links.tsx
, импортируйте компонент Link
из next/link
и замените тег <a>
на <Link>
:
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
// ...
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
Как видите, компонент Link
похож на использование тегов <a>
, но вместо <a href="…">
вы используете <Link href="…">
.
Сохраните изменения и проверьте работу на локальном сервере. Теперь вы должны иметь возможность переходить между страницами без полной перезагрузки. Хотя части вашего приложения рендерятся на сервере, полной перезагрузки страницы не происходит, что создаёт ощущение нативного веб-приложения. Почему так?
Автоматическое разделение кода и предзагрузка
Для улучшения навигации Next.js автоматически разделяет код вашего приложения по сегментам маршрутов. Это отличается от традиционных SPA на React, где браузер загружает весь код приложения при первоначальной загрузке страницы.
Разделение кода по маршрутам означает изоляцию страниц. Если на определённой странице возникнет ошибка, остальная часть приложения продолжит работать. Это также уменьшает объём кода, который браузеру нужно обрабатывать, что делает ваше приложение быстрее.
Более того, в production-режиме, когда компоненты <Link>
появляются в области просмотра браузера, Next.js автоматически предзагружает код для связанного маршрута в фоновом режиме. К моменту, когда пользователь нажимает на ссылку, код целевой страницы уже будет загружен в фоне, что делает переход между страницами практически мгновенным!
Узнайте больше о принципах работы навигации.
Шаблон: Отображение активных ссылок
Распространённый UI-шаблон — показывать активную ссылку, чтобы указать пользователю текущую страницу. Для этого нужно получить текущий путь пользователя из URL. Next.js предоставляет хук usePathname()
, который можно использовать для проверки пути и реализации этого шаблона.
Поскольку usePathname()
— это React-хук, вам нужно преобразовать nav-links.tsx
в клиентский компонент. Добавьте директиву "use client"
React в начало файла, затем импортируйте usePathname()
из next/navigation
:
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
// ...
Затем присвойте путь переменной pathname
внутри вашего компонента <NavLinks />
:
export default function NavLinks() {
const pathname = usePathname();
// ...
}
Примечание:
nav-links.tsx
— не специальный файл для Next.js, он может называться как угодно. Если вы переименуете его, убедитесь, что обновили соответствующие импорты.
Вы можете использовать библиотеку clsx
, представленную в главе о стилизации CSS, для условного применения классов, когда ссылка активна. Когда link.href
совпадает с pathname
, ссылка должна отображаться с синим текстом и светло-голубым фоном.
Вот окончательный код для nav-links.tsx
:
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
// ...
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
{
'bg-sky-100 text-blue-600': pathname === link.href,
},
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
Сохраните и проверьте на локальном сервере. Теперь активная ссылка должна подсвечиваться синим цветом.