Navigation: Link and useRouter
Next.js has the Link component for links between pages. It renders an ordinary a tag, but navigation happens without a full reload: the browser loads only the new page, and the layout stays in place. For navigating from code, for example after a button click, there is the useRouter hook.
The Link component
Let us add a menu to the root layout:
// app/layout.tsx
import Link from 'next/link';
import './globals.css';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<nav>
<Link href="/">Home</Link> | <Link href="/posts">Posts</Link> |{' '}
<Link href="/about">About</Link>
</nav>
{children}
</body>
</html>
);
}The href prop is the page address. Click the links and watch the Network tab in the developer tools: the page is not reloaded as a whole.
Links to posts
Let us turn the titles in the posts list into links:
// app/posts/page.tsx
import Link from 'next/link';
const posts = [
{ slug: 'hello-nextjs', title: 'Hello, Next.js' },
{ slug: 'server-components', title: 'Server components' },
];
export default function PostsPage() {
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/posts/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
);
}The address is built with a template string. For now the links lead to a 404 — the post page comes in the dynamic routes lesson.
Prefetching
When a Link appears in the visible part of the screen, Next.js loads the target page in advance (in the built version of the site). That is why a click responds almost instantly.
Navigating from code
The useRouter hook only works in a client component — a file with the 'use client' directive on its first line. Such components get their own lesson.
// components/BackButton.tsx
'use client';
import { useRouter } from 'next/navigation';
export default function BackButton() {
const router = useRouter();
return <button onClick={() => router.back()}>Back</button>;
}Use the button on any page: import BackButton from '@/components/BackButton' and then <BackButton /> in the markup. A click returns to the previous page.
Router methods
| Method | What it does |
|---|---|
router.push('/posts') | Goes to the address |
router.replace('/posts') | Goes there without adding a history entry |
router.back() | Goes back |
router.refresh() | Requests the current page data from the server again |
Active link
The usePathname hook from next/navigation returns the current address, such as /posts. Compare it with href to highlight the menu item of the page the visitor is on.
Common mistake
Importing useRouter from next/router. That is the old Pages Router hook; in the App Router it throws "NextRouter was not mounted". The correct import is next/navigation.