Author: Michael Hungbo
Introduction
If you have built websites and applications on the web, then you're very likely to have used a common method for navigation. Traditionally, navigation is often achieved with the HTML anchor element (<a></a>
). The anchor element is primarily used for navigating within and outside websites and webpages, and it serves its purpose pretty well.
In this article, we'll introduce you to Next.js <Link/>
component, a similar method of navigation to the native anchor element but with additional built-in features for optimization. The Next.js Link component has additional benefits, such as options to customize navigation behavior through props and improved performance and SEO metrics.
Steps we'll cover:
Prerequisites
You'll need a good knowledge of writing and understanding code in JavaScript and React to grasp this article.
- You'll also need a next.js project to get started. Visit here to see how to create a next.js app.
- Next, run
npm install styled-components
in the terminal to install styled-components. We'll use it for styling in this tutorial.
Introducing the <Link/>
component
The Link component provides a method of client-side navigation within Next.js applications. It's recommended over the native anchor tag because it has many built-in features that help improve application performance and SEO ranking. Some of these features include preloading page content and faster navigation since routing is handled with JavaScript.
In addition, client-side navigation with the Link component does not involve full page reloads, which is very significant in application performance and user experience.
The Link component is exported from the next/link
core module. Here's a basic demo showing its usage:
import Link from 'next/link'
function Home () {
return (
<>
<h1> Visit our About page</>
<Link href="/about"> About Us </Link>
</>
)
}
export default Home
The Link component props
Required props
href
The Next.js Link component requires a single mandatory prop: href
.
href
specifies the path or URL to navigate to. This could be an absolute URL, a relative URL, or a URL object.
Absolute URL
<Link href="https://nextjs.org/docs"> Read the Docs </Link>
Relative URL
<Link href="/about"> About Us </Link>
URL objects
With a URL object, we can resolve URLs using strings and parameters passed as an object to the Next.js Link component. Here's a demo showing how to use it in the Link component.
<Link
href={{
pathname: '/products',
query: { product: '1' },
}}
>
<a>Search for product 1</a>
</Link>
The above example will resolve the href
value into: /products/?product=1
.
Optional props
as
The as
prop is used with href
when using dynamic routes. It specifies a link decorator, which provides additional information about a URL that can be used in analytics (such as ads and affiliate programs) and tracking webpage performance.
The decorator usually appears after a '?'
in the URL of a webpage and does not change the destination of the URL. An example of a URL with link decoration is 'http://www.refine.com/blog/article?referrer_source=newsletter'
.
Example
Create new folders and files in the pages
folder of your application to look like below:
📦pages
┣ 📂api
┃ ┗ 📜hello.js
┣ 📂products
┃ ┣ 📜index.js
┃ ┗ 📜[product].js
┣ 📜index.js
┗ 📜_app.
Next, add the following code to pages/products/index.js
:
import React from "react";
import Link from "next/link";
const ProductsList = () => {
const productIDs = ["1", "2", "3"];
return (
<>
<div>
<h1>Products List</h1>
</div>
{productIDs.map((product, key) => (
<Link
href="/products/[product]"
as={`products/${product}/?referrer_source=newsletter`}
key={key}
>
<a>
<h1>{product}</h1>
<p>Learn more about product {product}</p>
</a>
</Link>
))}
</>
);
};
export default ProductsList;
And in pages/products/[product].js
, add the following code:
import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
const Product = () => {
const router = useRouter();
const productID = router.query.product;
return (
<>
<h1>
<Link href='/products'><a>Go back to Products</a></Link>
</h1>
<div>
<h5>Product {productID} Details Page</h5>
</div>
</>
)
}
export default Product
If you navigate to localhost:3000/products
you should see the page rendered like so:
Now, if you click on any of the products, you'll be taken to the details page of each product which is a dynamic route.
In the above demo we can see the URL of every product contains a link decorator, ?referrer_source=newsletter
, which does not affect the link's destination.
passHref
The passHref
prop forces the Next.js Link component to send the href
prop to its child. This is important when the child of </Link>
is a custom component that wraps an anchor tag (<a>
).
Not adding the passHref
prop in this scenario will hurt SEO and accessibility because the <a>
tag will not have the href
property. It is disabled by default.
Example
Edit the code in pages/products/index.js
to the following:
import React from "react";
import Link from "next/link";
+ import styled from 'styled-components'
+ const CustomLink = styled.a`
+ color: red;
+ font-size: 30px;
+ `
const ProductsList = () => {
const productIDs = ["1", "2", "3"];
return (
<>
<div>
+ <NavLink href='/' name='Home'/>
<h1>Products List</h1>
</div>
{productIDs.map((product, key) => (
<Link
href="/products/[product]"
as={`products/${product}/?referrer_source=newsletter`}
key={key}
>
<a>
<h1>{product}</h1>
<p>Learn more about product {product}</p>
</a>
</Link>
))}
</>
);
};
+ const NavLink = ({ href, name }) => {
+ return (
+ <Link href={href} passHref>
+ <CustomLink>{name}</CustomLink>
+ </Link>
+ )
+ };
export default ProductsList;
Now if you navigate to localhost:8000
a custom red link should be displayed like below:
prefetch
Preloading page content can drastically improve application performance. The prefetch
prop allows the preloading of pages in the background and is enabled by default in the Next.js Link component. It only works in production, and if you wish to disable preloading, you can configure it like so:
<Link href='/products' prefetch={false}><a>Click me!</a></Link>
replace
The replace prop changes how navigation works by replacing the current history state instead of adding a new URL into the stack. This can be demonstrated by clicking on the back
button in the navigation bar in the browser.
Edit the content in pages/index.js
to the following:
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import styles from "../styles/Home.module.css";
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>Introduction to next/link</h1>
<h1>
<Link href='/products'>Go to products page</Link>
</h1>
</main>
</div>
);
}
The page should look like below:
If you click on the Go to products page
link, watch how the application navigation works when we click on the back navigation button without the replace
prop in the GIF below.
Next, find the part that contains the code below in pages/products/index.js
and add the replace
prop to it like so:
...
{productIDs.map((product, key) => (
<Link
href="/products/[product]"
as={`products/${product}/?referrer_source=newsletter`}
key={key}
+ replace={product === '3' ? true : false}
>
<a>
<h1>{product}</h1>
<p>Learn more about product {product}</p>
</a>
</Link>
))}
...
Now let's go back to the browser and see how the navigation works with replace
prop.
As you can see in the GIF above, when we visited the product 3 details page and then clicked the back navigation button, instead of returning to the products page, we were taken to the home page instead.
scroll
Clicking on a link using the Link component will scroll to the top of the destination page by default. It's also possible to scroll to a specific section of the new page by using hash ids (the part of a URL after a #
). You can disable the default behavior or hash ids by setting scroll={false}
on the Link component.
Disable scroll to top
<Link href="/blog/intro" scroll={false}>
<a>Disables scrolling to the top</a>
</Link>
Scroll to a specific section in a webpage using hash ids
<Link href="https://refine.dev/blog/mui-datagrid-refine/#material-ui-datagrid-component">
<a>Scroll to a specific section</a>
</Link>
locale
The locale
prop is used to navigate users to different versions of a webpage based on the user's preferred locale (language and region). For example, we may have a blog that is read by English and French users, and we need to render the blog content in English for English users and in French for French users.
We can serve English or French users different versions of our webpage in their preferred language by configuring the i18n
object in next.config.js
. Read more about configuring locales here.
shallow
The shallow
props let us update the path of the current page without running any of Next.js data fetching methods (that is, getStaticProps
, getServerSideProps
or getInitialProps
). The updated pathname
and query
associated with the new URL can be accessed by the router
object provided by useRouter or withRouter.
Here's a good example showing how to use shallow routing in your web pages.
Conclusion
The Next.js Link component simplifies client-side navigation, and we recommend using it over the native anchor element for routing in your next.js applications. In this article, you learned how to use Link
and configure its behavior using props to suit your use cases. You also learned how important concepts such as dynamic routes and URL objects work using the Link component.
We hope you found this article useful in getting started with next/link and client-side navigation in next.js. You can read the Next.js Link component docs here for references and additional information.
** Writer: Michael Hungbo**
Build your React-based CRUD applications without constraints
Modern CRUD applications are required to consume data from many different sources from custom API’s to backend services like Supabase, Hasura, Airtable and Strapi.
Check out refine, if you are interested in a backend agnostic, headless framework which can connect 15+ data sources thanks to built-in providers and community plugins.
refine is an open-source React-based framework for building CRUD applications without constraints.
It can speed up your development time up to 3X without compromising freedom on styling, customization and project workflow.
refine is headless by design and it connects 30+ backend services out-of-the-box including custom REST and GraphQL API’s.
Visit refine GitHub repository for more information, demos, tutorials, and example projects.