Navigating Between Pages in Next.js is a fundamental aspect of web development, and in Next.js, this process is made efficient with several advanced features. This chapter focuses on adding navigation links to your dashboard layout, ensuring seamless transitions without full page refreshes. We will delve into the use of the next/link
component, displaying active links using the usePathname()
hook, and understanding how navigation works in Next.js.
Table of content
- Introduction
- Using the
next/link
Component - Showing Active Links with
usePathname()
- Navigating Between Pages in Next.js – How it Works
- Automatic Code-Splitting and Prefetching
- The Mechanics of Next.js Navigation
- Back and Forward Navigation
- Routing Between
pages/
andapp/
- Showing Active Links
- Conclusion
- FAQs
Introduction
Efficient navigation is crucial for a smooth user experience in any web application. In this chapter, we explore the tools and techniques provided by Next.js to optimize page navigation, minimizing disruptions and enhancing performance.
Using the next/link
Component
Traditional HTML navigation relies on the <a>
element, which causes a full page reload with each navigation. In Next.js, the <Link>
component is used to handle client-side navigation seamlessly.
Implementing the <Link>
Component
To implement the <Link>
component, follow these steps:
- Import the Component: Begin by importing the
Link
component fromnext/link
in your navigation file.
import Link from 'next/link';
- Replace
<a>
Tags: Replace your existing<a>
tags with<Link>
. Here is an example code snippet fornav-links.tsx
:
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
This approach ensures that navigating between the pages does not cause a full page reload, resulting in a smoother user experience.
Showing Active Links with usePathname()
To enhance user navigation, it’s helpful to highlight the currently active link. This can be achieved using the usePathname()
hook.
Implementing usePathname()
- Convert to a Client Component: Add the directive
"use client"
at the top of your file and importusePathname
fromnext/navigation
.
'use client';
import { usePathname } from 'next/navigation';
- Determine Active Link: Inside your
NavLinks
component, use thepathname
to determine which link is active.
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
{ 'bg-sky-100 text-blue-600': pathname === link.href }
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
The clsx
library is used to conditionally apply styles, highlighting the active link.
How Navigation Works in Next.js
Next.js optimizes navigation through automatic code-splitting and prefetching, ensuring efficient performance and a seamless user experience.
Automatic Code-Splitting and Prefetching
Next.js automatically splits your application code by route segments, unlike traditional single-page applications where all code is loaded initially. This isolation ensures that only the necessary code is loaded for each route.
When <Link>
components are rendered, Next.js prefetches the linked routes in the background. This preloading ensures near-instant transitions when users navigate to those routes.
The Mechanics of Next.js Navigation
Next.js employs a hybrid approach for routing and navigation, combining server-side and client-side techniques.
Code Splitting
Code splitting reduces the amount of code transferred and executed, enhancing performance. Next.js server components automatically split code by route segments, loading only the required code on navigation.
Prefetching
Prefetching routes can be done in two ways:
- Automatic Prefetching: The
<Link>
component prefetches routes as they become visible in the viewport. - Programmatic Prefetching: Use the
useRouter
hook’srouter.prefetch()
method to prefetch routes programmatically.
Caching
Next.js employs an in-memory client-side cache, storing the payload of prefetched routes and visited segments. This cache reduces server requests and data transfer on navigation, improving performance.
Partial Rendering
Partial rendering only re-renders route segments that change, preserving shared segments. This reduces data transfer and execution time, enhancing performance.
Soft Navigation
Soft navigation ensures only the changed route segments re-render, preserving client React state. This approach prevents full page reloads and maintains a smooth navigation experience.
Back and Forward Navigation
Next.js maintains scroll positions for backward and forward navigation, reusing route segments from the router cache to enhance performance.
Routing Between pages/
and app/
When migrating from pages/
to app/
, Next.js handles hard navigation between the two, leveraging probabilistic checking to minimize false positives. This ensures smooth transitions and maintains performance.
Showing Active Links
Highlighting active links enhances user experience by clearly indicating the current page. Using the usePathname()
hook and conditional styling with the clsx
library, active links can be visually distinguished.
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
{ 'bg-sky-100 text-blue-600': pathname === link.href }
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
Conclusion
Navigating between pages in Next.js is optimized through features like code splitting, prefetching, caching, and partial rendering. By leveraging these tools, you can ensure a smooth and efficient user experience in your web application.
FAQs
<Link>
component in Next.js differ from the traditional <a>
tag? The <Link>
component in Next.js allows for client-side navigation without causing a full page reload, unlike the traditional <a>
tag, which triggers a full page refresh.
Automatic code-splitting in Next.js divides the application code into smaller bundles by route segments, loading only the necessary code for each route, improving performance.
Prefetching in Next.js preloads route data in the background as links become visible in the viewport, ensuring near-instant transitions when users navigate to those routes.
usePathname()
hook in Next.js? The usePathname()
hook in Next.js retrieves the current path, allowing developers to implement features like highlighting the active link based on the user’s current location.
Next.js uses an in-memory client-side cache to store prefetched route segments and visited routes, reducing server requests and data transfer on navigation.
Partial rendering in Next.js re-renders only the route segments that change on navigation, preserving shared segments and reducing data transfer and execution time.
Next topics
Read next blog to create next.js app Creating Layouts and Pages on Next.js