kentcdodds / mdx-bundler

šŸ¦¤ Give me MDX/TSX strings and I'll give you back a component you can render. Supports imports!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mdx-bundler should support Next.js 13 data fetching strategies via `use()` hook

NateRadebaugh opened this issue Ā· comments

  • mdx-bundler version: 9.0.1
  • node version: v16.18.0
  • npm version:: 8.19.2
  • next version: 13.0.0

Relevant code or config

What you did:

Updated my nextjs app to use Next.js 13. Replaced getStaticProps with use(getData())

What happened:

image

From what I understand the use hook is for Client Components, and I'm not sure if mdx-bundler was ever intended to run in the browser.

For Server usage i.e when porting getStaticProps/getServerSideProps, the import error can be fixed with serverComponentsExternalPackages in next.config -> Link to docs

experimental: {
  serverComponentsExternalPackages: ["mdx-bundler"],
}

Full config:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    serverComponentsExternalPackages: ["mdx-bundler"],
  },
};

module.exports = nextConfig;

Then combining it with an async Server Component at page level (instead of use)

// page.tsx
import { bundleMDX } from 'mdx-bundler'
import { getMDXComponent } from 'mdx-bundler/client'

async function getPageBundle() {
  const result = await bundleMDX({
    source: '<h1>Hello World</h1>',
  });

  return result;
}

export default async function Page() {
  const { code } = await getPageBundle();

  const Component = React.useMemo(() => getMDXComponent(code), [code])

  return <Component />
}

For hydration you may want to move the <Component /> logic into its own Client Component, passing code down as a prop.

// page.tsx
import { bundleMDX } from 'mdx-bundler'
import { MDXComponent } from '../components/MDXComponent'

async function getPageBundle() {
  const result = await bundleMDX({
    source: '<h1>Hello World</h1>',
  });

  return result;
}

export default async function Page() {
  const { code } = await getPageBundle();

  return <MDXComponent code={code} />
}
// MDXComponent.tsx
"use client";

import { getMDXComponent } from 'mdx-bundler/client'

export function MDXComponent({ code }) {
  const Component = React.useMemo(() => getMDXComponent(code), [code])

  return <Component />
}

Thanks, that worked!