Навигация и ссылки

В Next.js существует два способа навигации между маршрутами:

На этой странице мы рассмотрим, как использовать <Link>, useRouter(), а также углубимся в принципы работы навигации.

<Link> — это встроенный компонент, расширяющий HTML-тег <a> для обеспечения предварительной загрузки и клиентской навигации между маршрутами. Это основной способ перехода между маршрутами в Next.js.

Для его использования необходимо импортировать его из next/link и передать пропс href:

import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}
import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}

Существуют и другие опциональные пропсы, которые можно передать в <Link>. Подробнее см. в справочнике API.

Примеры

Ссылки на динамические сегменты

При ссылках на динамические сегменты можно использовать шаблонные строки и интерполяцию для генерации списка ссылок. Например, для создания списка постов блога:

app/blog/PostList.js
import Link from 'next/link'

export default function PostList({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

Проверка активных ссылок

Для определения активной ссылки можно использовать usePathname(). Например, чтобы добавить класс к активной ссылке, можно проверить, совпадает ли текущий pathname с href ссылки:

'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Links() {
  const pathname = usePathname()

  return (
    <nav>
      <ul>
        <li>
          <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
            Главная
          </Link>
        </li>
        <li>
          <Link
            className={`link ${pathname === '/about' ? 'active' : ''}`}
            href="/about"
          >
            О нас
          </Link>
        </li>
      </ul>
    </nav>
  )
}
'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Links() {
  const pathname = usePathname()

  return (
    <nav>
      <ul>
        <li>
          <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
            Главная
          </Link>
        </li>
        <li>
          <Link
            className={`link ${pathname === '/about' ? 'active' : ''}`}
            href="/about"
          >
            О нас
          </Link>
        </li>
      </ul>
    </nav>
  )
}

Прокрутка к id

По умолчанию App Router в Next.js прокручивает страницу к началу нового маршрута или сохраняет позицию прокрутки при навигации назад и вперед.

Если необходимо прокрутить страницу к определенному id при навигации, можно добавить к URL хэш-ссылку # или передать ее в пропс href. Это возможно, поскольку <Link> рендерится как элемент <a>.

<Link href="/dashboard#settings">Настройки</Link>

// Результат
<a href="/dashboard#settings">Настройки</a>

Отключение восстановления прокрутки

По умолчанию App Router в Next.js прокручивает страницу к началу нового маршрута или сохраняет позицию прокрутки при навигации назад и вперед. Чтобы отключить это поведение, можно передать scroll={false} в компонент <Link> или scroll: false в router.push() или router.replace().

// next/link
<Link href="/dashboard" scroll={false}>
  Dashboard
</Link>
// useRouter
import { useRouter } from 'next/navigation'

const router = useRouter()

router.push('/dashboard', { scroll: false })

Хук useRouter()

Хук useRouter позволяет программно изменять маршруты.

Этот хук можно использовать только в клиентских компонентах, и он импортируется из next/navigation.

app/page.js
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}

Полный список методов useRouter см. в справочнике API.

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

Принципы работы маршрутизации и навигации

App Router использует гибридный подход к маршрутизации и навигации. На сервере код вашего приложения автоматически разделяется по сегментам маршрутов. На клиенте Next.js предварительно загружает и кэширует сегменты маршрутов. Это означает, что при переходе пользователя на новый маршрут страница в браузере не перезагружается, а повторно рендерятся только измененные сегменты маршрута, что улучшает опыт навигации и производительность.

1. Предварительная загрузка (Prefetching)

Предварительная загрузка — это способ загрузить маршрут в фоновом режиме до того, как пользователь перейдет на него.

В Next.js есть два способа предварительной загрузки маршрутов:

  • Компонент <Link>: Маршруты автоматически загружаются, когда они появляются в области видимости пользователя. Это происходит при первой загрузке страницы или при прокрутке.
  • router.prefetch(): Хук useRouter можно использовать для программной предварительной загрузки маршрутов.

Поведение предварительной загрузки <Link> различается для статических и динамических маршрутов:

  • Статические маршруты: По умолчанию prefetch имеет значение true. Весь маршрут предварительно загружается и кэшируется.
  • Динамические маршруты: По умолчанию prefetch работает автоматически. Предварительно загружается и кэшируется только общий макет до первого файла loading.js на 30s. Это снижает затраты на загрузку всего динамического маршрута и позволяет показать мгновенное состояние загрузки для лучшей визуальной обратной связи.

Можно отключить предварительную загрузку, установив пропс prefetch в false.

Подробнее см. в справочнике API <Link>.

Полезно знать:

  • Предварительная загрузка не работает в режиме разработки, только в продакшене.

2. Кэширование

Next.js имеет клиентский кэш в памяти под названием Router Cache. При навигации по приложению полезная нагрузка React Server Component для предварительно загруженных и посещенных сегментов маршрутов сохраняется в кэше.

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

Подробнее о работе Router Cache и его настройке.

3. Частичный рендеринг

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

Например, при переходе между двумя соседними маршрутами /dashboard/settings и /dashboard/analytics будут рендериться страницы settings и analytics, а общий макет dashboard сохранится.

Как работает частичный рендеринг

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

4. Мягкая навигация (Soft Navigation)

По умолчанию браузер выполняет жесткую навигацию между страницами. Это означает, что браузер перезагружает страницу и сбрасывает состояние React, такое как хуки useState в вашем приложении, и состояние браузера, такое как позиция прокрутки или активный элемент. Однако в Next.js App Router использует мягкую навигацию. Это означает, что React рендерит только измененные сегменты, сохраняя состояние React и браузера, без полной перезагрузки страницы.

5. Навигация назад и вперед

По умолчанию Next.js сохраняет позицию прокрутки при навигации назад и вперед и повторно использует сегменты маршрутов в Router Cache.