next/link и навигация в Next.js
Next.js предоставляет несколько способов навигации: компонент Link для декларативной навигации, хук useRouter для программной и функции redirect/permanentRedirect для серверной.
Компонент Link
Link это основной способ навигации. Он рендерит тег <a>, но перехватывает клик и выполняет клиентскую навигацию без полной перезагрузки:
import Link from 'next/link'
export default function Navigation() {
return (
<nav>
<Link href="/docs">База знаний</Link>
<Link href="/problems">Задачи</Link>
<Link href="/roadmap">Роадмап</Link>
</nav>
)
}
Prefetching
По умолчанию Link prefetch'ит страницу, когда она попадает в viewport. Это делает переходы мгновенными:
// Prefetch включен по умолчанию
<Link href="/docs/next/ssg">SSG в Next.js</Link>
// Отключить prefetch для редко посещаемых страниц
<Link href="/settings" prefetch={false}>Настройки</Link>
Для статических роутов prefetch загружает весь RSC Payload. Для динамических загружается до ближайшего loading.tsx.
Динамические href
<Link href={`/docs/${doc.slug}`}>
{doc.title}
</Link>
// С объектом
<Link
href={{
pathname: '/problems',
query: { difficulty: 'hard' }
}}
>
Сложные задачи
</Link>
Активная ссылка
Для подсветки текущей страницы используй usePathname:
'use client'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
export function NavLink({
href,
children
}: {
href: string
children: React.ReactNode
}) {
const pathname = usePathname()
const isActive = pathname === href
return (
<Link
href={href}
className={isActive ? 'text-blue-600 font-bold' : 'text-neutral-600'}
>
{children}
</Link>
)
}
useRouter
Для программной навигации в клиентских компонентах:
'use client'
import { useRouter } from 'next/navigation'
export function LoginButton() {
const router = useRouter()
const handleLogin = async () => {
const result = await login()
if (result.success) {
router.push('/dashboard')
}
}
return <button onClick={handleLogin}>Войти</button>
}
Методы useRouter
| Метод | Описание |
|---|---|
router.push(url) | Навигация к URL (добавляет в историю) |
router.replace(url) | Навигация без добавления в историю |
router.back() | Назад по истории |
router.forward() | Вперед по истории |
router.refresh() | Обновляет текущий роут (перезапрашивает данные с сервера) |
router.prefetch(url) | Предзагрузка роута |
Важно:
useRouter из next/navigation (App Router) и useRouter из next/router (Pages Router) это разные хуки с разным API. В App Router нет router.query, вместо него используй useSearchParams.
Серверная навигация
В серверных компонентах и Server Actions используй redirect:
// В Server Action
'use server'
import { redirect } from 'next/navigation'
export async function createProblem(formData: FormData) {
const problem = await db.problem.create({ ... })
redirect(`/problems/${problem.id}`)
}
// В серверном компоненте
import { redirect } from 'next/navigation'
export default async function Page() {
const user = await getUser()
if (!user) redirect('/auth/login')
return <Dashboard user={user} />
}
useSearchParams
Для работы с query-параметрами:
'use client'
import { useSearchParams } from 'next/navigation'
export function FilterPanel() {
const searchParams = useSearchParams()
const difficulty = searchParams.get('difficulty')
return <p>Фильтр: {difficulty || 'все'}</p>
}
usePathname
Для получения текущего пути:
'use client'
import { usePathname } from 'next/navigation'
export function Breadcrumbs() {
const pathname = usePathname()
const segments = pathname.split('/').filter(Boolean)
return (
<nav>
{segments.map((segment, i) => (
<span key={i}>{segment}</span>
))}
</nav>
)
}
Полезные ресурсы
- nextjs.org/docs — Linking and Navigating
- Link API Reference
- useRouter API Reference