1

I asked this question in the Next.js Github Issues, but didn't get any answer.

I copied the code from next.js/examples/app-dir-mdx. in the following codeSandbox - the only additional change I made was:

In the .mdx pages, I have added relative links to one of the other pages in the folder like below:

  • [next page](./plain-markdown).

I added the customization for the anchor tag in mdx-components.tsx. But after the customization, the links are not being redirected properly.

  • when clicking on http://localhost:3001/blog/test, i'm being redirected to http://localhost:3001/test.

Please note that the url in the DOM and even when I hover over the link show up as http://localhost:3001/blog/test

But what I noticed is that the url in the anchor tag href attribute is different when using app directory:

  • before app directory: <a href="/blog/plain-markdown">
  • after app directory: <a href="./plain-markdown">

Please note that this isue is caused on when I override the default <a> element to use the next/link component. with the default<`> element, it works fine

I found this article which states that the next/link behavior is changed in Next 13.

Starting with Next.js 13, <Link> renders as <a>, so attempting to use <a> as a child is invalid.

Gangula
  • 5,193
  • 4
  • 30
  • 59

1 Answers1

1

This has been resolved in Nextjs 13.4.5.


OLD

Honestly, this looks like a bug in next/link when using Next 13 app router. <Link> component doesn't handle relative links correctly even when used in regular pages outside of mdx. I can only assume that Next MDX does some special processing of relative links, which breaks when you specify your custom link component.

In the meantime, I came up with the following workaround.

"use client";

import * as React from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";

function absolute(pathname: string, href: string) {
  if (
    href.startsWith("http://") ||
    href.startsWith("https://") ||
    href.startsWith("/")
  ) {
    return href;
  }

  const stack = pathname.split("/");
  const parts = href.split("/");
  stack.pop();

  for (let i = 0; i < parts.length; i++) {
    if (parts[i] == ".") continue;
    if (parts[i] == "..") stack.pop();
    else stack.push(parts[i]);
  }
  return stack.join("/");
}

export default function Anchor({
  href,
  children,
}: React.JSX.IntrinsicElements["a"]) {
  const pathname = usePathname();
  return href !== undefined ? (
    <Link href={absolute(pathname, href)}>{children}</Link>
  ) : null;
}

Hope this helps.

Gangula
  • 5,193
  • 4
  • 30
  • 59
Igor Danchenko
  • 1,980
  • 1
  • 3
  • 13