vercel / next.js

The React Framework
https://nextjs.org
MIT License
124.73k stars 26.62k forks source link

MDX support width appDir enabled #47523

Open Doodidan opened 1 year ago

Doodidan commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Home
    Binaries:
      Node: 18.14.0
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.2.5-canary.16
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), MDX (@next/mdx)

Link to the code that reproduces this issue

https://github.com/GoshaEgorian/next-mdx-bug-reproduction

To Reproduce

  1. npm run dev
  2. localhost:3000

Describe the Bug

MDX cannot be rendered with new app dir 'cause of context

Expected Behavior

MDX renders normally

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

KonstantinSimeonov commented 1 year ago

I've ran into this as well. I tried splitting up the mdx code as components, adding a "use client" directive in them and then rendering them in a page, but this didn't work.

// stuff.mdx

"use client"

# hello
// page.tsx
import Hello from "./stuff.mdx"

export default function DoesntWork() {
  return <Hello />
}
traversng commented 1 year ago

@Doodidan I believe you need to import your mdx file in your page.tsx. Your example code shows just a page.md file with markdown.

  1. Turn that page into content.mdx
  2. Create a page.tsx file
  3. Import that content into page.tsx like
    
    import Content from './content.mdx'

export default function ShouldWork() { return }



This should work in `@latest`
MatthewCaseres commented 1 year ago

I am having the same issue and have a reproduction with an mdx file - https://github.com/MatthewCaseres/mdx-repro. I am going to close my duplicate issue and just follow this issue.

@traversng do you have an example I can clone from where it is working properly with latest version?

tannerabread commented 1 year ago

Hi @MatthewCaseres for your case, if you move mdx-components.tsx to the root of your project it fixes the issue

MatthewCaseres commented 1 year ago

@tannerabread Thank you! The repo is updated to help as a working example for others who are having issues.

Doodidan commented 1 year ago

@Doodidan I believe you need to import your mdx file in your page.tsx. Your example code shows just a page.md file with markdown.

1. Turn that page into `content.mdx`

2. Create a `page.tsx` file

3. Import that content into `page.tsx` like
import Content from './content.mdx'

export default function ShouldWork() {
  return <Content />
}

This should work in @latest

Yes, I found working eample with this. But plain .mdx files without page.tsx work fine with old architecture. So, I find it as a bug.

kossidts commented 1 year ago

Thanks for the solution @Doodidan. It only works when I set the "use client"; directive at the top of page.tsx. Without that I am still getting the createContext-error. To me it's not clear why the directive is necessary since I am using plain md and it's not mentioned once in the official documentation.

mnieber commented 1 year ago

@kossidts In my case, it was fixed when adding the mdx-components.tsx file as mentioned in the docs, and adding mdxRs: true in the config. It does work (for me) without use client.

damien commented 1 year ago

Hey folks! Chiming in that I've encountered this error as a somebody new to NextJS and getting up to speed with MDX. The instructions as is in the live docs invariably result in the same message reported above:

error createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component

So my question: What's the intended path for usage of MDX going forward? What should I expect?

I'm fine using the implementation proposed (import MDX content into a TSX component and render from there with the appropriate client/server pragma)--but it'd be nice to know if the documentation is out of date or this is an ephemeral implementation issue within NextJS 13.x.

Cheers!

mnieber commented 1 year ago

@damien Are you using the mdx-components.tsx file and setting mdxRs: true in the config?

mizlan commented 1 year ago

@damien Are you using the mdx-components.tsx file and setting mdxRs: true in the config?

I did this but am still experiencing the error. I don't know how to debug what is causing this, in part because I don't understand how mdx-components.tsx is supposed to fix this.

mnieber commented 1 year ago

@mizlan Just to be sure, I followed these instructions: https://nextjs.org/docs/app/building-your-application/configuring/mdx (there is a possible gotcha of following the instructions for pages instead of app).

mizlan commented 1 year ago

Hmm, yeah I followed that. Also to note, I am trying to use it via a dynamic import, like as here (except his works and mine doesn't, for some reason...)

https://github.com/rafaelalmeidatk/rafaelalmeidatk.com/blob/9be13f0f199221344b9b78e24ec3c7b933de0f4a/src/lib/posts.ts#L25

kossidts commented 1 year ago

@mizlan I am not sure if this is the solution but I think you need to configure pageExtensions to include md and mdx as shown in https://nextjs.org/docs/pages/building-your-application/configuring/mdx

// next.config.js
...
const nextConfig = {
    pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
    ...
}
...
mizlan commented 1 year ago

Ah I resolved it, I did something dumb. (I had the "if you're gonna use MDXProvider" part uncommented without actually using that)

Thanks for your time and help!

levino commented 11 months ago

Hi @MatthewCaseres for your case, if you move mdx-components.tsx to the root of your project it fixes the issue

This is the solution!

x-tropy commented 10 months ago

Yes, in my experience mdx-components.tsx is necessary even if you don't want to customize markdown elements. Just create that file and put it in the root folder with content like this:

import React from "react"
import type { MDXComponents } from "mdx/types"

export function useMDXComponents(components: MDXComponents): MDXComponents {
    return {
        ...components
    }
}
ibnumusyaffa commented 9 months ago

placing mdx-components.tsx in the root of project fix this issue

cruzluna commented 8 months ago

Ensure mdx-components.tsx is at the root ie src/mdx-components.tsx image

useEffects commented 8 months ago

Not working with contentlayer + mdx + app

elie222 commented 7 months ago

This seems to work:

'use client';

import Content from "./content.mdx";

export default function Page() {
  return <Content />;
}
elie222 commented 7 months ago

How I moved from ContentLayer to Next MDX. ContentLayer seems to no longer be maintained and has a lot of bugs: elie222/inbox-zero@cf42b0b (#79)

debsouryadatta commented 5 months ago

Hi @MatthewCaseres for your case, if you move mdx-components.tsx to the root of your project it fixes the issue

Thanks! It helped.

mastoj commented 3 months ago

Anyone that has a good explanation to why I have to add "use client" to my page for it to render?

This is what my page.tsx looks like:

"use client";

import { Slide } from "../_slides/config";

type Props = {
  params: {
    id: string;
  };
};

const page = ({ params }: Props) => {
  const slideId = parseInt(params.id, 10);
  return (
    <div>
      <Slide slideId={slideId} />
    </div>
  );
};

export default page;

As I see it that should completely valid without "use client".

WendaoLee commented 2 months ago

Okay,after 30mins checking,I finally found the solution for me:

  1. Move the mdx-components.tsx to the ./src or the parent folder of /app (as the official document said).
  2. Delete the "use client" annotation at the top of mdx-components.tsx,which I dumbly wrote it for trying solving client-components error.
  3. Delete the .next folder. That's the major evil bug for me.The bad cache made me even done right thing,the error still occurs.
arsadii commented 5 days ago

Okay,after 30mins checking,I finally found the solution for me:

  1. Move the mdx-components.tsx to the ./src or the parent folder of /app (as the official document said).
  2. Delete the "use client" annotation at the top of mdx-components.tsx,which I dumbly wrote it for trying solving client-components error.
  3. Delete the .next folder. That's the major evil bug for me.The bad cache made me even done right thing,the error still occurs.

Still doesn't work for me :(

arsadii commented 5 days ago

@Doodidan I believe you need to import your mdx file in your page.tsx. Your example code shows just a page.md file with markdown.

1. Turn that page into `content.mdx`

2. Create a `page.tsx` file

3. Import that content into `page.tsx` like
import Content from './content.mdx'

export default function ShouldWork() {
  return <Content />
}

This should work in @latest

Yes, I found working eample with this. But plain .mdx files without page.tsx work fine with old architecture. So, I find it as a bug.

this works but need to add "use client" directive on page.tsx