Client-Side Navigation with <Link>¶
Up until now, we've used standard <a> tags for navigation (e.g., href="/dashboard"). While <a> tags work, Next.js provides a specialized component, <Link> from next/link, that offers significant performance advantages and a better user experience for client-side navigation.
Understanding the Benefits of next/link¶
The <Link> component offers several key benefits over native <a> tags for internal navigation within your Next.js application:
- Client-Side Transitions: When you click a
<Link>component, Next.js performs a client-side navigation. This means the browser doesn't have to request the entire HTML document from the server again. Instead, Next.js only fetches the necessary data for the new page and updates the DOM, resulting in much faster and smoother transitions. - Prefetching:
<Link>components automatically prefetch the JavaScript and data for linked pages that are within the viewport (or that are hovered over). This means that by the time a user clicks a link, the target page's resources are often already loaded, leading to instant navigations. - Accessibility:
<Link>components ensure proper accessibility by automatically managing focus and other attributes. - SEO: Next.js ensures that
<Link>components are still crawlable by search engines, so your application remains SEO-friendly.
Implementing Navigation between Task App Pages¶
Let's refactor our Header and DashboardLayout components to use <Link> for navigation. This will make our Task App's navigation faster and more efficient.
- Update
components/Header.tsx: We need to importLinkfromnext/linkand replace the<a>tags withLinkcomponents.
components/Header.tsx (Update this file)
// components/Header.tsx
// This is a reusable Header component for the Task Management App.
// It will display the app title and will eventually hold navigation links.
// Updated to use Next.js's <Link> component for optimized client-side navigation.
import Link from 'next/link'; // Import the Link component
// It's a Server Component by default, as no 'use client' directive is present.
export default function Header() {
return (
<header className="bg-gradient-to-r from-blue-600 to-indigo-700 text-white p-4 shadow-lg rounded-b-lg">
<div className="container mx-auto flex justify-between items-center py-2">
{/* Application Title - now a Link to the homepage */}
<Link href="/" className="text-3xl font-extrabold tracking-tight hover:text-blue-200 transition duration-300">
My TaskFlow
</Link>
{/* Navigation */}
<nav>
<ul className="flex space-x-6">
<li>
{/* Link to the Dashboard */}
<Link href="/dashboard" className="hover:text-blue-200 transition duration-300">
Dashboard
</Link>
</li>
<li>
{/* Example link to a dynamic task page (replace with actual ID later) */}
<Link href="/tasks/sample-task-123" className="hover:text-blue-200 transition duration-300">
Sample Task
</Link>
</li>
{/* We'll add more navigation links here later, e.g., for login/signup */}
</ul>
</nav>
</div>
</header>
);
}
- Update
app/dashboard/layout.tsx: We'll also update the navigation links within our dashboard sidebar to use<Link>.
app/dashboard/layout.tsx (Update this file)
// app/dashboard/layout.tsx
// This layout specifically applies to the /dashboard route and any of its nested routes.
// Updated to use Next.js's <Link> component for optimized client-side navigation.
import Link from 'next/link'; // Import the Link component
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex flex-col md:flex-row min-h-[calc(100vh-180px)]">
{/* Dashboard Sidebar */}
<aside className="w-full md:w-64 bg-gray-50 p-6 shadow-md rounded-lg md:mr-6 mb-6 md:mb-0">
<h3 className="text-xl font-semibold text-gray-700 mb-4">Dashboard Navigation</h3>
<nav>
<ul className="space-y-3">
<li>
{/* Link to the Dashboard root */}
<Link
href="/dashboard"
className="block p-3 rounded-md text-blue-600 hover:bg-blue-100 transition duration-200"
>
All Tasks
</Link>
</li>
<li>
{/* Example link to a dynamic task page within the dashboard context */}
<Link
href="/tasks/another-sample-id"
className="block p-3 rounded-md text-gray-700 hover:bg-gray-200 transition duration-200"
>
View Sample Task
</Link>
</li>
<li>
{/* Example for future nested route */}
<Link
href="/dashboard/settings"
className="block p-3 rounded-md text-gray-700 hover:bg-gray-200 transition duration-200"
>
Settings
</Link>
</li>
</ul>
</nav>
</aside>
{/* Main content area for the dashboard */}
<section className="flex-grow bg-white p-6 shadow-md rounded-lg">
{children}
</section>
</div>
);
}