Skip to main content

Navigation with Link, useRouter, and redirect

8/28
Chapter 2 App Router, Layouts, and Navigation

Navigation with Link, useRouter, and redirect

15 min read Lesson 8 / 28

Next.js provides several navigation primitives, each suited to different scenarios.

Link is the primary way to navigate between pages. It prefetches routes in the viewport automatically:

import Link from 'next/link';

// Basic link
<Link href="/about">About</Link>

// Dynamic route
<Link href={`/blog/${post.slug}`}>{post.title}</Link>

// With query params
<Link href={{ pathname: '/blog', query: { page: 2 } }}>
    Next Page
</Link>

// Replace instead of push (no history entry)
<Link href="/login" replace>Sign In</Link>

// Disable prefetching for rare links
<Link href="/admin" prefetch={false}>Admin</Link>
'use client';

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

interface NavLinkProps {
    href: string;
    children: React.ReactNode;
}

export function NavLink({ href, children }: NavLinkProps) {
    const pathname = usePathname();
    const isActive = pathname === href || pathname.startsWith(`${href}/`);

    return (
        <Link
            href={href}
            className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
                isActive
                    ? 'bg-blue-100 text-blue-700'
                    : 'text-gray-600 hover:text-gray-900'
            }`}
        >
            {children}
        </Link>
    );
}

useRouter for Programmatic Navigation

'use client';

import { useRouter } from 'next/navigation';

export function SearchForm() {
    const router = useRouter();

    function handleSearch(query: string) {
        router.push(`/search?q=${encodeURIComponent(query)}`);
    }

    function goBack() {
        router.back();
    }

    function refresh() {
        router.refresh(); // Re-fetch Server Component data
    }

    return (/* ... */);
}

Server-Side Redirect

Use redirect() from next/navigation inside Server Components and Server Actions:

import { redirect } from 'next/navigation';

export default async function ProtectedPage() {
    const session = await getSession();

    if (!session) {
        redirect('/login'); // Throws internally — no return needed
    }

    return <Dashboard />;
}

The redirect() function in Server Actions will redirect after the action completes, making it perfect for post-form-submission navigation.