Skip to main content

Next.js Link Component

Introduction

In traditional websites, navigating between pages requires full page reloads, which can lead to a slower user experience. Next.js provides a built-in Link component that enables client-side navigation between pages in your application. This means that page transitions happen without a full page refresh, resulting in a smoother and more app-like experience for users.

The Link component is one of the core components in Next.js and is essential for building efficient navigation in your applications.

Basic Usage

The Link component is imported from next/link and wraps around your clickable elements, typically an anchor tag (<a>).

jsx
import Link from 'next/link';

function Navigation() {
return (
<nav>
<ul>
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/about">About</Link>
</li>
<li>
<Link href="/blog">Blog</Link>
</li>
</ul>
</nav>
);
}

In this example, clicking on any of these links will navigate to the respective page without a full page reload.

When you use the Link component:

  1. Next.js automatically prefetches the linked page in the background when the link appears in the viewport (for production builds)
  2. When the link is clicked, Next.js intercepts the navigation
  3. The browser URL is updated using the History API
  4. Only the necessary components are re-rendered, not the entire page
  5. The focus is maintained, improving accessibility

This approach significantly improves performance compared to traditional page navigations.

The href Prop (Required)

The href prop is the only required prop for the Link component and specifies the path or URL to navigate to.

jsx
<Link href="/products">Products</Link>

You can also use object syntax for more complex URLs:

jsx
<Link 
href={{
pathname: '/products',
query: { category: 'electronics', sort: 'price' },
}}
>
Electronic Products
</Link>

This will generate a link to /products?category=electronics&sort=price.

The as Prop

The as prop allows you to customize the URL that appears in the browser address bar without changing the actual page that gets loaded.

jsx
<Link href="/products/[id]" as="/products/123">
Product 123
</Link>
note

In newer versions of Next.js (12.2+), you'll typically use dynamic routes instead of the as prop in most cases.

The replace Prop

By default, Next.js adds a new entry to the browser's history stack when navigating. If you set the replace prop to true, the current history entry will be replaced instead:

jsx
<Link href="/dashboard" replace>
Go to Dashboard
</Link>

This is useful for redirections where you don't want the user to be able to go back to the previous page.

The scroll Prop

By default, Next.js scrolls to the top of the page after navigation. You can disable this by setting scroll={false}:

jsx
<Link href="/long-page" scroll={false}>
Navigate without scrolling to top
</Link>

The prefetch Prop

By default, Next.js automatically prefetches pages linked by the Link component when they appear in the viewport. You can disable this behavior:

jsx
<Link href="/large-page" prefetch={false}>
Navigate without prefetching
</Link>

Advanced Usage

Next.js supports dynamic routes, and the Link component works seamlessly with them:

jsx
// Linking to a dynamic route
<Link href={`/products/${productId}`}>View Product</Link>

// For more complex parameters
<Link
href={{
pathname: '/products/[id]/reviews',
query: { id: productId },
}}
>
Product Reviews
</Link>

Sometimes you might want to use the Link component with your own custom components. Here's how to do it:

jsx
import Link from 'next/link';
import Button from './Button';

export default function CustomLinkButton() {
return (
<Link href="/dashboard" passHref legacyBehavior>
<Button>Dashboard</Button>
</Link>
);
}

In Next.js 13+, you can simplify this:

jsx
import Link from 'next/link';
import Button from './Button';

export default function CustomLinkButton() {
return (
<Link href="/dashboard" asChild>
<Button>Dashboard</Button>
</Link>
);
}

The Link component doesn't apply any styles by itself. You can style the underlying elements as you normally would:

jsx
<Link href="/contact">
<span className="nav-link">Contact Us</span>
</Link>

Or with CSS-in-JS:

jsx
import styled from 'styled-components';
import Link from 'next/link';

const StyledLink = styled(Link)`
color: #0070f3;
text-decoration: none;
&:hover {
text-decoration: underline;
}
`;

export default function Navigation() {
return (
<StyledLink href="/about">About Us</StyledLink>
);
}

Real-world Examples

Building a Navigation Menu

Here's how you might build a simple navigation menu using the Link component:

jsx
import Link from 'next/link';
import { useRouter } from 'next/router';
import styles from './Navigation.module.css';

export default function Navigation() {
const router = useRouter();

return (
<nav className={styles.nav}>
<ul className={styles.navList}>
{[
{ href: '/', text: 'Home' },
{ href: '/about', text: 'About' },
{ href: '/services', text: 'Services' },
{ href: '/contact', text: 'Contact' },
].map(({ href, text }) => (
<li key={href} className={styles.navItem}>
<Link
href={href}
className={router.pathname === href ? styles.activeLink : styles.link}
>
{text}
</Link>
</li>
))}
</ul>
</nav>
);
}

Building a Pagination Component

Here's how you might implement pagination using the Link component:

jsx
import Link from 'next/link';
import styles from './Pagination.module.css';

export default function Pagination({ currentPage, totalPages }) {
return (
<div className={styles.pagination}>
{currentPage > 1 && (
<Link
href={{ pathname: '/blog', query: { page: currentPage - 1 } }}
className={styles.pageLink}
>
Previous
</Link>
)}

{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
<Link
key={page}
href={{ pathname: '/blog', query: { page } }}
className={`${styles.pageLink} ${
currentPage === page ? styles.activePage : ''
}`}
>
{page}
</Link>
))}

{currentPage < totalPages && (
<Link
href={{ pathname: '/blog', query: { page: currentPage + 1 } }}
className={styles.pageLink}
>
Next
</Link>
)}
</div>
);
}

Best Practices

  1. Use the Link component for internal navigation instead of plain <a> tags to take advantage of client-side navigation.

  2. Don't add an <a> tag inside the Link component in Next.js 13+, as it's automatically created. In earlier versions, you should include it.

  3. Avoid using onClick handlers to navigate. Instead, use the Link component or the router.push() method from useRouter hook.

  4. Use the legacyBehavior prop with older versions when nesting custom components inside Link.

  5. Be mindful of prefetching for extremely large applications. You might want to disable it for rarely visited pages.

Common Issues and Solutions

If your Link component doesn't navigate correctly, make sure:

  • The href prop is correctly formatted
  • You're not preventing default behavior with an onClick handler
  • You've correctly set up your page structure in the /pages directory (or app directory in Next.js 13+)

Remember that in Next.js 13+, the Link component renders an <a> tag by default. Apply styles to this tag rather than to the Link component itself.

Summary

The Next.js Link component is a powerful tool for implementing client-side navigation in your applications. It offers significant performance benefits over traditional page navigation by:

  • Enabling client-side transitions
  • Automatically prefetching pages
  • Preventing full page reloads
  • Maintaining focus and scroll position

By utilizing the various props and features of the Link component, you can create highly performant and user-friendly navigation systems in your Next.js applications.

Additional Resources

Practice Exercises

  1. Create a simple multi-page Next.js application with a navigation menu using the Link component.
  2. Build a product listing page with dynamic routes and client-side navigation to product detail pages.
  3. Implement a blog with pagination using the Link component and query parameters.
  4. Create a breadcrumb navigation component using Link.
  5. Experiment with the different props of the Link component to understand their effects on navigation behavior.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)