Навигация и Link
Link
Основной способ навигации:
import Link from 'next/link';
<Link href="/about">О нас</Link>
<Link href={`/posts/${post.id}`}>{post.title}</Link>
Преимущества
- Клиентская навигация — без перезагрузки
- Предзагрузка — Next.js заранее загружает страницу при наведении
- Scroll restoration — сохраняет позицию
- Prefetch — только для видимых ссылок в viewport
Prefetch
По умолчанию включён. Отключить:
<Link href="/heavy" prefetch={false}>Тяжёлая страница</Link>
replace
Не добавляет запись в историю:
<Link href="/login" replace>Войти</Link>
scroll
Не скроллить к началу:
<Link href="/posts" scroll={false}>Посты</Link>
useRouter
Программная навигация:
'use client';
import { useRouter } from 'next/navigation';
export default function Button() {
const router = useRouter();
return (
<>
<button onClick={() => router.push('/about')}>О нас</button>
<button onClick={() => router.replace('/login')}>Войти</button>
<button onClick={() => router.back()}>Назад</button>
<button onClick={() => router.forward()}>Вперёд</button>
<button onClick={() => router.refresh()}>Обновить</button>
</>
);
}
- push — новая запись в истории
- replace — заменить текущую
- back, forward — по истории
- refresh — перезагрузить данные серверных компонентов
usePathname
Текущий путь:
'use client';
import { usePathname } from 'next/navigation';
export function Nav() {
const pathname = usePathname();
return (
<nav>
<Link href="/" className={pathname === '/' ? 'active' : ''}>Главная</Link>
<Link href="/about" className={pathname === '/about' ? 'active' : ''}>О нас</Link>
</nav>
);
}
Активная ссылка
Компонент:
'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 || pathname.startsWith(href + '/');
return (
<Link href={href} className={isActive ? 'active' : ''}>
{children}
</Link>
);
}
redirect
В серверных компонентах и Server Actions:
import { redirect } from 'next/navigation';
export default async function Page() {
const user = await getUser();
if (!user) redirect('/login');
return <h1>Профиль</h1>;
}
redirect бросает исключение — код после не выполняется.
redirect vs router.push
- redirect — сервер, для условных редиректов
- router.push — клиент, для обработчиков
notFound
import { notFound } from 'next/navigation';
if (!post) notFound();
useSelectedLayoutSegment
Для активных табов:
'use client';
import { useSelectedLayoutSegment } from 'next/navigation';
export function Tabs() {
const segment = useSelectedLayoutSegment();
return (
<nav>
<Link href="/dashboard/settings" className={segment === 'settings' ? 'active' : ''}>Настройки</Link>
<Link href="/dashboard/profile" className={segment === 'profile' ? 'active' : ''}>Профиль</Link>
</nav>
);
}
Возвращает активный сегмент под текущим layout.
Программная навигация с query
'use client';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const params = new URLSearchParams(searchParams);
params.set('page', '2');
router.push(`${pathname}?${params}`);
Итоги
Link— основной способ- Prefetch включён по умолчанию
useRouterдля программной навигацииusePathnameдля активных ссылокredirectв серверных компонентахuseSelectedLayoutSegmentдля табов