0

There's plenty of information about how to use Next.js' Link module if the child itself has an <a> tag within it (passHref), but there seems to be no indication that this should be needed for child component that aren't creating their own <a> tag. But I have run into a situation where a "decorator" component being a child of a Link component causes the link to not get rendered at all.

import React from 'react'
import Link from 'next/link'
import type { NextPage } from 'next'

interface Props {
  children: string
}

// A simple functional component that transforms its child to more readable form
const HexString = ({ children: hex }: Props)  => {
  const shortHex = hex.substring(0, 8) + '...' + hex.substring(hex.length - 6)
  return (
    <span title={hex} className="hex-string">
      {shortHex}
    </span>
  )
}

// Page component wishing to use that decorator inside a Link
const MyPage: NextPage = () => {
  return (
    <div>
      <Link href="/index">
        <HexString>0x0102030405060708090a0b0c0d0e0f</HexString>
      </Link>
    </div>
  )
}
export default MyPage

What gets rendered to the page is only the hex-string span and its contents. The <a> tag the Link is supposed to add is not in the DOM.

How can I get the Link component to properly render an anchor tag around this styled span tag from another component?

MidnightLightning
  • 6,715
  • 5
  • 44
  • 68

2 Answers2

1

This is a difference in behavior between Next.js v12 and v13. Details about this change are in https://github.com/vercel/next.js/pull/36436. This is not yet in the documentation because it's an "experimental" feature)

In versions 12 and less, the behavior was to not include a literal anchor tag for Link:

// Renders: <strong onClick={nextLinkClickHandler}>Hello</strong>. No `<a>` is included.
<Link href="/about">
  <strong>Hello</strong>
</Link>


// Renders: <strong onClick={nextLinkClickHandler}>Hello</strong>. No `<a>` is included.
<Link href="/about">
  <CustomComponent />
</Link>

Note this happens when the child of a Link component is either a custom component (as this question shows) or an HTML tag.

In Next.js v13, this will be changing to always render an <a> anchor tag wrapped around those child components.

In Next.js v12, that behavior can be opted-into by setting the experimental.newNextLinkBehavior flag.

So, to ensure that an anchor tag is always present, either set experimental.newNextLinkBehavior to true (if using Next.js v12), or add an empty <a> tag around the child component:

// Page component wishing to use that decorator inside a Link
const MyPage: NextPage = () => {
  return (
    <div>
      <Link href="/index">
        <a><HexString>0x0102030405060708090a0b0c0d0e0f</HexString></a>
      </Link>
    </div>
  )
}
MidnightLightning
  • 6,715
  • 5
  • 44
  • 68
-1

I think the issue here is that the Link component cannot hav the div element as a parent. Remove the div tags encircling Link and you should be good.

Jevon Cochran
  • 1,565
  • 2
  • 12
  • 23
  • The Link component renders itself as an anchor tag, and it's valid to have an anchor tag inside a div tag. The result is the same whether the Link element is the top level element returned, inside a div, paragraph, or list element container. – MidnightLightning Mar 08 '23 at 05:50