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:
app/blog/test/page.mdx
<a>
to use next/link
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.
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:
<a href="/blog/plain-markdown">
<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.
This has been resolved in Nextjs 13.4.5.
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.