Links in Next.js – External, Internal, Dynamic, Query or Path Param Examples

In this detailed guide on using Links in the Next js application, we will cover various use cases on adding links for example:

  • Internal Links
  • External Links
  • Passing Query or Path Parameters in Links
  • Fetch Multiple Query Params in the URL
  • Get or Set Dynamic Routes
  • Styling Active Links
  • Programmatically Navigate on Click

Let’s dive deep and learn with examples of each type of link:

 

Internal Links

Links between the pages of the application come under internal linking. To link between pages in a Next.js app, we use the Link component from next/linkas shown below:

import Link from 'next/link';

function Nav() {
  return (
    <nav>
      <Link href="/">
        <a>Home</a>
      </Link> 
      <Link href="/about">
        <a>About</a>
      </Link>
    </nav>
  );
}

The Link component helps to prefetch the page in the background, so when a user clicks, it loads instantly.

 

Advantages of using Link components:

  • The Link component is used instead of anchor tags to prevent page reloads.
  • We can wrap the a tag inside Link to get styles/attributes.
  • Use the href prop to pass the page path.
  • Relative paths can be given starting with /.

 

External Links

Links to external sites or resources can be given by adding the native/ regular a tags:

function Footer() {
  return (
    <footer>
      <a href="https://www.example.com">Website</a> 
    </footer>
  );
}

 

Passing Query or Path Parameters in Links

For dynamic pages, which can accept query or path params, we can pass those values in the Link as shown below inside the href:

<Link href="/blog/123?title=Next.js">
  <a>Go to Blog 123</a>
</Link>

 

Or through the pathname:

<Link href="/blog/123/nextjs-is-awesome">
  <a>Go to Blog 123</a>
</Link>

 

Get or Set Dynamic Routes

The query params or path params passed in the URL via link or any other method can be fetched by using the url.query as shown below:

First, we will define a page called /post which accepts a postId parameter:
// pages/post.js

export default function Post({ post }) {
  return <div>{post.title}</div>  
}

export async function getServerSideProps({ params }) {
  const postId = params.postId;

  const response = await fetch(`https://api.example.com/posts/${postId}`);
  const post = await response.json();

  return {
    props: {
      post
    }
  }
}

 

Now we can access the postId parameter using url.query in getServerSideProps:

export async function getServerSideProps({ params }) {

  // Access parameter
  const postId = params.postId; 

  // Or access via url.query
  const { postId } = params.url.query;

  // Fetch post data
  
  return {
    props: {
      post
    }
  }
}

 

To link to this page, we need to pass the postId parameter:

<Link href="/post?postId=123">
  <a>Post 123</a> 
</Link>

The postId=123 query parameter will be available as params.url.query.postId in getServerSideProps.

 

Get or Set Dynamic Routes

Dynamic Routes are used to pass dynamic information to pages showing changing information like fetching data from remote API.

Create a pages/posts/[id].js file to match dynamic ID values:

// pages/posts/[id].js

import { useRouter } from 'next/router';

export default function Post() {
  const router = useRouter();
  const { id } = router.query;

  return <h1>Post {id}</h1>;
}

This will match any routes like /posts/1, /posts/abc etc. Then we can access the id parameter from the router.

 

Next, we’ll implement getServerSideProps to fetch the actual post data:

export async function getServerSideProps({ params }) {
  const response = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await response.json();

  return {
    props: {
      post
    }
  };
}

 

To link to a dynamic page, we need to pass the ID dynamically:

<Link href="/posts/[id]" as={`/posts/${post.id}`}>
  <a>{post.title}</a>
</Link>

The as prop allows interpolating the value in the browser URL bar.

 

We can render the actual post data thereafter as shown below:

export default function Post({ post }) {
  return (
    <>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </>
  );
}

 

Styling Active Links

It’s important to let users know about active links by highlighting them using CSS styles. In this section, we will get to know how to style the active links by checking the current URL route.

Here is a sample Navbar component with Link components:

import Link from 'next/link';

export default function Navbar() {
  return (
    <nav>
      <Link href="/">
        <a>Home</a>
      </Link>

      <Link href="/about">
        <a>About</a>
      </Link>

      <Link href="/contact">
        <a>Contact</a>
      </Link>
    </nav>
  );
}

Next, we’ll import the useRouter hook to access the router object:

import { useRouter } from 'next/router';

export default function Navbar() {

  const router = useRouter();

  // ... rest of component

}

 

We can now conditionally check the route and apply active styling:

<Link href="/">
  <a className={router.pathname === '/' ? 'active' : ''}>Home</a>
</Link>

<Link href="/about">
 <a className={router.pathname === '/about' ? 'active' : ''}>About</a>
</Link>

<style jsx>{`
  .active {
    color: red;
  }
`}</style>

 

The active class will be applied for the current page due to the route check. We can also use the activeClassName prop directly on the Link:

<Link href="/" activeClassName="active">
  <a>Home</a>
</Link>

<Link href="/about" activeClassName="active">
 <a>About</a> 
</Link>

This will automatically apply the class to the active link. Next we can add custom CSS style for active links

.active {
  /* Styles */
  color: red; 
}

This allows styling the currently active link in your Next.js app!

 

Styling Dynamic Active Links

In the previous section, we got to know how to style some predefined links. But usually, we have dynamic build paths having query or path params. Let’s see how to add an active class on dynamic links:

Create the dynamic link:

<Link href="/post/[postId]/[category]" as={`/post/${post.id}/${post.category}`}>
  <a>{post.title}</a> 
</Link>

 

Next, in our Navbar component we can check the asPath from router:

import { useRouter } from 'next/router'

export default function Navbar(){

  const router = useRouter()
  
  return (
    <Link 
       href="/post/[postId]/[category]"
       as={`/post/123/cars`}
       activeClassName="active"
    >
      <a>Cars</a>
    </Link>
  )
}

To check if this link is active:

<Link
  href="/post/[postId]/[category]" 
  as={`/post/123/cars`}
  activeClassName={router.asPath.startsWith('/post/123/cars') ? 'active' : ''}
>
  <a>Cars</a>
</Link>

We check if router asPath starts with the link href.

 

Programmatically Navigate

Instead of adding Links in the template part, we can navigate programmatically via functions.

Import the useRouter hook:

import { useRouter } from 'next/router';

 

Then access the router object:

export default function Home() {

  const router = useRouter();

  const handleClick = () => {
    // Navigate programatically  
  }

  return (
    <button onClick={handleClick}>
      Click to navigate
    </button>
  )
}

 

Now we can use the various router methods:

Navigate to a new page:

const handleClick = () => {
  router.push('/about')
}

 

Replace current page:

const handleClick = () => {
  router.replace('/contact')
}

 

Go back:

const handleClick = () => {
  router.back()
}

 

Go forward (if history exists):

const handleClick = () => {
  router.forward()
}

 

Pass Route Parameters

router.push('/post?id=123')

// Or with dynamic route
router.push('/post/[id]', '/post/123')

 

Conclusion

We discussed various ways to implement links inside templates or navigate pages programmatically. Also, we discussed how to get or set dynamic URL params including query or path parameters.

We discussed how to style the active links which are static or dynamic in nature. Hope this will be helpful…

Leave a Comment

Your email address will not be published. Required fields are marked *