I'm trying to make use of @mdx-js runtime with next.js to load MDX dynamically, but even a simple example that makes use of a custom shortcut React component fails when the render function of the embedding component is called again.
Here's an example page, adopted from the demo
import React from 'react';
import MDX from '@mdx-js/runtime';
const Alert = (props) => <div className="alert" style={{ color: 'red' }}>{props.children}</div>
const mdx = "<Alert>hi</Alert>";
export default () => {
const scope = { Alert }
return (
<MDX scope={scope}>{mdx}</MDX>
);
}
when loading this page, upon the second call to render, I see this error:
SyntaxError: Identifier 'Alert' has already been declared
at new Function (<anonymous>)
at index (/home/gback/website/node_modules/@mdx-js/runtime/dist/cjs.js:206:12)
at processChild (/home/gback/website/node_modules/react-dom/cjs/react-dom-server.node.development.js:3043:14)
at resolve (/home/gback/website/node_modules/react-dom/cjs/react-dom-server.node.development.js:2960:5)
at ReactDOMServerRenderer.render (/home/gback/website/node_modules/react-dom/cjs/react-dom-server.node.development.js:3435:22)
at ReactDOMServerRenderer.read (/home/gback/website/node_modules/react-dom/cjs/react-dom-server.node.development.js:3373:29)
at renderToString (/home/gback/website/node_modules/react-dom/cjs/react-dom-server.node.development.js:3988:27)
at render (/home/gback/website/node_modules/next/dist/next-server/server/render.js:3:298)
at renderPage (/home/gback/website/node_modules/next/dist/next-server/server/render.js:46:1020)
at Object.ctx.renderPage (webpack-internal:///./pages/_document.js:145:26)
at Function.getInitialProps (webpack-internal:///./node_modules/next/dist/pages/_document.js:133:19)
at Function.MyDocument.getInitialProps (webpack-internal:///./pages/_document.js:156:83)
at loadGetInitialProps (/home/gback/website/node_modules/next/dist/next-server/lib/utils.js:5:101)
at renderToHTML (/home/gback/website/node_modules/next/dist/next-server/server/render.js:46:1330)
at async /home/gback/website/node_modules/next/dist/next-server/server/next-server.js:68:285
at async /home/gback/website/node_modules/next/dist/next-server/server/next-server.js:67:142
This is from next.js getInitialProps that is part of their server-side rendering.
It appears that Alert was in the scope from the first call to render, and the compiler (babel?) rejected an attempt to declare it again (?)
"@mdx-js/loader": "^1.6.7",
"@mdx-js/runtime": "^1.6.7",
"next": "*9.4.4",
Running on Linux under node v12.16.1 testing with Firefox
I could create a self-contained example if there's interest, unless somebody tells me that this use is simply not supported.
It seems to me, though, that MDX may throw this error whenever the render function of the embedding component is called twice. This, however, I can't explain since in React's paradigm it's React that determines how often and when the render() function is called and it should certainly not assume that it's called only once. So this would seem like an outlandish bug, something else may be going on.
It should work as in the provided demo
Thanks for opening up an issue! I think we have a bit of a docs bug that doesn't properly show the difference between scope and components. For components, what you want to do is pass them as the components prop rather than scope. Here's an example of both in action:
import React from "react";
import MDX from "@mdx-js/runtime";
const Alert = props => (
<div className="alert" style={{ color: "red" }}>
{props.children}
</div>
);
const mdx = "<Alert>hi {foo}</Alert>";
export default function App() {
return (
<MDX components={{ Alert }} scope={{ foo: "foo" }}>
{mdx}
</MDX>
);
}
Most helpful comment
Thanks for opening up an issue! I think we have a bit of a docs bug that doesn't properly show the difference between
scopeandcomponents. For components, what you want to do is pass them as thecomponentsprop rather than scope. Here's an example of both in action: