Ссылки и навигация
Маршрутизатор Next.js позволяет выполнять переходы между страницами на стороне клиента, подобно одностраничному приложению.
Для таких переходов предоставляется React-компонент Link
.
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/about">About Us</Link>
</li>
<li>
<Link href="/blog/hello-world">Blog Post</Link>
</li>
</ul>
)
}
export default Home
В примере выше используются несколько ссылок. Каждая из них сопоставляет путь (href
) с известной страницей:
/
→pages/index.js
/about
→pages/about.js
/blog/hello-world
→pages/blog/[slug].js
Любой <Link />
в области просмотра (изначально или при прокрутке) будет предварительно загружен по умолчанию (включая соответствующие данные) для страниц, использующих статическую генерацию (Static Generation). Данные для серверного рендеринга (server-rendered) загружаются только при клике на <Link />
.
Ссылки на динамические пути
Вы также можете использовать интерполяцию для создания пути, что удобно для динамических сегментов маршрута. Например, для отображения списка постов, переданных компоненту как пропс:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
В примере используется
encodeURIComponent
для обеспечения совместимости пути с utf-8.
Альтернативно, используя URL-объект:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: post.slug },
}}
>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
Теперь вместо интерполяции для создания пути мы используем URL-объект в href
, где:
pathname
— имя страницы в директорииpages
. В данном случае/blog/[slug]
.query
— объект с динамическим сегментом. В данном случаеslug
.
Доступ к маршрутизатору
Примеры
Для доступа к объекту router
в React-компоненте можно использовать useRouter
или withRouter
.
Обычно мы рекомендуем использовать useRouter
.
Императивная маршрутизация
Примеры
next/link
должен покрывать большинство ваших потребностей в маршрутизации, но вы также можете выполнять навигацию на стороне клиента без него — ознакомьтесь с документацией next/router
.
Следующий пример показывает, как выполнять базовую навигацию по страницам с помощью useRouter
:
import { useRouter } from 'next/router'
export default function ReadMore() {
const router = useRouter()
return (
<button onClick={() => router.push('/about')}>
Нажмите, чтобы узнать больше
</button>
)
}
Поверхностная маршрутизация (Shallow Routing)
Примеры
Поверхностная маршрутизация позволяет изменять URL без повторного выполнения методов получения данных, включая getServerSideProps
, getStaticProps
и getInitialProps
.
Вы получите обновленные pathname
и query
через объект router
(добавляемый useRouter
или withRouter
), без потери состояния.
Для включения поверхностной маршрутизации установите параметр shallow
в true
. Рассмотрим следующий пример:
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// Текущий URL — '/'
function Page() {
const router = useRouter()
useEffect(() => {
// Всегда выполняем навигацию после первого рендера
router.push('/?counter=10', undefined, { shallow: true })
}, [])
useEffect(() => {
// Счетчик изменился!
}, [router.query.counter])
}
export default Page
URL обновится до /?counter=10
, но страница не перезагрузится — изменится только состояние маршрута.
Вы также можете отслеживать изменения URL через componentDidUpdate
, как показано ниже:
componentDidUpdate(prevProps) {
const { pathname, query } = this.props.router
// проверяем, изменились ли пропсы, чтобы избежать бесконечного цикла
if (query.counter !== prevProps.router.query.counter) {
// загружаем данные на основе нового запроса
}
}
Ограничения
Поверхностная маршрутизация работает только для изменений URL на текущей странице. Например, предположим, у нас есть другая страница pages/about.js
, и вы выполняете:
router.push('/?counter=10', '/about?counter=10', { shallow: true })
Поскольку это новая страница, текущая страница будет выгружена, загрузится новая, и будут ожидаться данные, несмотря на указание поверхностной маршрутизации.
При использовании поверхностной маршрутизации с middleware не гарантируется, что новая страница соответствует текущей, как это было ранее без middleware. Это связано с тем, что middleware может динамически переписывать маршруты, что нельзя проверить на стороне клиента без загрузки данных, которая пропускается при поверхностной маршрутизации. Поэтому изменения при поверхностной маршрутизации всегда должны рассматриваться как поверхностные.
Динамические маршруты
Динамические маршруты позволяют добавлять пользовательские параметры в URL. Узнайте, как создавать динамические маршруты и подробнее об их использовании.
Пользовательское приложение (Custom App)
Управление инициализацией страниц и добавление общего макета путем переопределения компонента App, используемого по умолчанию в Next.js.