Search code examples
next.jscomponents

Pass a dynamic 'href' from mdx into NextJs 'Anchor' custom styled component


I'm trying to access the 'href' data in a markdown tag through MDX and into a custom styled NextJS component.

At the moment I want someone to be able to write in markdown:

[Website](http://www.website.com)

and get the data into a custom style component something like this:

./components/md/Anchor.tsx 

function Anchor({ hrefProp, text }) {
 
  return <a className="text-blue-600 my-4 text-base" href={hrefProp} target="_blank" rel="noopener">{text}</a>;
}
export default Anchor;

The url 'http://website.com' is getting lost going from mdx to jsx, I'm only able to tap into the {text}.

Ideally I don't have to change the markdown syntax much at all to achieve this. Any suggestions?

I thought maybe trying to put the href data through the meta or frontmatter as a way to do this.


Solution

  • Assuming that you are using @next/mdx and @mdx-js/react, you can access the href prop via the href prop in your Anchor component.

    1. Implement styled link component:
    // components/mdx/Anchor.tsx
    
    import * as React from "react";
    
    export default function Anchor({
      href,
      children,
      ...rest
    }: React.JSX.IntrinsicElements["a"]) {
      return (
        <a
          href={href}
          target="_blank"
          rel="noreferer noopener"
          className="text-blue-600 my-4 text-base"
          {...rest}
        >
          {children}
        </a>
      );
    }
    
    1. Add MDXProvider with custom link component to your _app.tsx:
    // pages/_app.tsx
    
    import * as React from "react";
    import { AppProps } from "next/app";
    import { MDXProvider } from "@mdx-js/react";
    
    import Anchor from "@/components/mdx/Anchor";
    import "@/styles/globals.css";
    
    const components = {
      a: Anchor,
    };
    
    export default function App({ Component, pageProps }: AppProps) {
      return (
        <MDXProvider components={components}>
          <Component {...pageProps} />
        </MDXProvider>
      );
    }
    
    1. Setup @next/mdx in next.config.js:
    // next.config.js
    
    const withMDX = require("@next/mdx")({
      extension: /\.mdx?$/,
      options: {
        remarkPlugins: [],
        rehypePlugins: [],
        providerImportSource: "@mdx-js/react",
      },
    });
    
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
    };
    
    module.exports = withMDX(nextConfig);
    

    Sandbox - https://codesandbox.io/p/sandbox/stackoverflow-76283549-h1fkf9?file=%2Fcomponents%2Fmdx%2FAnchor.tsx