Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

External link is not working in Next.js when you want to use Link component

I was very surprised that a simple Link component is not working in Next.js when you want to use an external URL and HTML Button tag inside it.

Below you can see how I tried to solve the problem:

Approach number 1:

<Link href="https://stackoverflow.com/">
  <button>StackOverflow</button>
</Link>

Approach number 2 (link without protocol):

<Link href="//stackoverflow.com/">
  <button>StackOverflow</button>
</Link>

Approach number 3 (link without protocol and with Link attribute prefetch set to false or even true):

<Link href="//stackoverflow.com/" prefetch={false}>
  <button>StackOverflow</button>
</Link>

IMPORTANT NOTE

Of course, mentioned case it's working when the URL is internal, like that:

<Link href="/stackoverflow">
  <button>StackOverflow</button>
</Link>

or when I will change HTML button tag into HTML A tag, like that:

<Link href="//stackoverflow.com/">
  <a>StackOverflow</a>
</Link>

In my case, I want to use the HTML button tag or any other UI component inside the Next.js Link component.

like image 863
Mario Boss Avatar asked Apr 06 '20 11:04

Mario Boss


People also ask

Can I use next link for external links?

To add an external link to the Next. js Link component we should use attribute passHref. This attribute is set to false by default. This attribute forces Link to send the href property to its child.

How do I link a component in NextJS?

Using <Link> As you can see, the Link component is similar to using <a> tags, but instead of <a href="…"> , you use <Link href="…"> . Note: Before Next.js 12.2, it was required that the Link component wrapped an <a> tag, but this is not required in versions 12.2 and above.

How can you tell if a link is internal or external?

By comparing the hostname of the string URL to the hostname of the web page URL, you can determine whether the link is external or not.


1 Answers

1. Solution for UI components inside Next.js Link component.

I have study Next.js documentation in more details and I found a very useful attribute to make an external link for any internal UI components (Semantic UI, Material UI, Reactstrap, etc.) inside Link component.

Let's take as an example a simple Semantic UI button component. To add an external link to the Next.js Link component we should use attribute passHref. This attribute is set to false by default. This attribute forces Link to send the href property to its child.

import { Button } from 'semantic-ui-react';
import Link from 'next/link';    

const Example = () => (
  <Link href="https://stackoverflow.com/" passHref={true}>
    <Button>StackOverflow</Button>
  </Link>
)

export default Example;

2. Solution for HTML elements (different that tag A)

Inside Next.js documentation you can find below sentences:

External URLs, and any links that don't require a route navigation using /pages, don't need to be handled with Link; use the anchor tag for such cases instead.

And I have to write that it is obvious, so in that case, if you need to use any other tag, for example, HTML button, you should use onClick event on it without Link component. The above code will look like this:

const clickHandle = () => {
  document.location.href = 'https://stackoverflow.com/';
}

const Example = () => (
  <button onClick={clickHandle}>StackOverflow</button>
)

export default Example;

UPDATE: Of course, I agree with devs who are writing that for external links we should not use the Link component. The best solution here is to use just pure HTML a tags or JS redirect solution on click event as it has been shown in point 2 (or any similar way). Worth to mention, that you can build your own component and based on the passed href attribute you can switch between Link component and HTML a tag, like that:

  // custom simple smart Link component
  import Link from 'next/link'; 
  
  const SmartLink = (link, url) => {
    const regEx = /^http/;

    return regEx.test(url) ? <Link href={url}>{link}</Link> : <a href={url}>{link}</a>;
  }
  
  export default SmartLink;

  // ways to call the component
  import SmartLink from 'path/to/SmartLink'; // set correct path

  // somewhere inside the render method
  // the below will use HTML A tag
  <SmartLink href="https://stackoverflow.com" link="external StackOverflow website" />
  // the below will use Next.js Link component
  <SmartLink href="/stackoverflow" link="internal StackOverflow page" />
like image 146
Mario Boss Avatar answered Sep 22 '22 12:09

Mario Boss