Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Example for MDXProvider with mdx-bundler for component substitution #195

Closed
Kuan-Ying opened this issue Nov 30, 2022 · 2 comments · Fixed by #227
Closed

Suggestion: Example for MDXProvider with mdx-bundler for component substitution #195

Kuan-Ying opened this issue Nov 30, 2022 · 2 comments · Fixed by #227
Labels

Comments

@Kuan-Ying
Copy link

Kuan-Ying commented Nov 30, 2022

Thank you for your work. This library is especially helpful for my work because I cannot setup Webpack for MDX compiler within my project, which uses an open-source framework and I have no control of the configs.

I have a minor suggestion for an opportunity to add an example for Component Substitution with MDXProvider.

  • mdx-bundler version: ^9.0.1
  • node version: 16.18.0
  • yarn version: 1.22.17

Relevant code or config

MDX files

Child.mdx
<Text>Awesome!</Text>
Parent.mdx
import Child from './Child.mdx';
<Child />

Server

const { code } = bundleMDX({
  source,
  mdxOptions(options: Record<string, any>) {
      return {
        ...options,
        providerImportSource: '@mdx-js/react',
      };
  }
});

UI

export const MDXComponent: React.FC<{
  code: string;
  frontmatter: Record<string, any>;
}> = ({ code }) => {
  const Component = useMemo(
    () => getMDXComponent(code),
    [code],
  );
  return (
    <MDXProvider components={{ Text: ({ children }) => <p>{children}</p> }}>
      <Component />
    </MDXProvider>
  );
};

What you did

I'm following MDX provider from the official MDX guide, and I would expect Parent.mdx can be compiled and run by React successfully.

What happened

It actually throws the following error in run-time:

Expected component `Text` to be defined: you likely forgot to import, pass, or provide it.

Problem description

It is unclear why the components are not passed to downstream MDX files. The Component Substitution section in this repo only gives an example to pass components to Component, which is cumbersome to pass down components if you have nesting MDX files.

After spending couple of hours diving into the unminified genereated code and source code of @mdx-js/es-build, I think I found the root cause.

When providerImportSource: '@mdx-js/react', the generated JS bundle merges the components from @mdx-js/react's useMDXComponents with the components from the props.
If we don't specify useMDXComponents in the globals, mdx-bundler will ship useMDXComponents as well as React.createContext to the bundle.

Now when the app render MDXComponent, MDXProvider has its own useMDXComponents and uses a different version of React.createContext. Because MDXProvider cannot alter the React.context for components in the MDX bundled code, components cannot be accessed in nested MDX files unless you manually pass components down.

Suggested solution

I think it would be nice to have a section in the document for the following solution:

Server

const globals = {
  '@mdx-js/react': {
    varName: 'MdxJsReact',
    namedExports: ['useMDXComponents'],
    defaultExport: false,
  },
};
const { code } = bundleMDX({
  source,
  globals,
  mdxOptions(options: Record<string, any>) {
      return {
        ...options,
        providerImportSource: '@mdx-js/react',
      };
  }
});

UI

import { MDXProvider, useMDXComponents } from '@mdx-js/react';
const MDX_GLOBAL_CONFIG = {
  MdxJsReact: {
    useMDXComponents,
  },
};
export const MDXComponent: React.FC<{
  code: string;
  frontmatter: Record<string, any>;
}> = ({ code }) => {
  const Component = useMemo(
    () => getMDXComponent(code, MDX_GLOBAL_CONFIG),
    [code],
  );
  return (
    <MDXProvider components={{ Text: ({ children }) => <p>{children}</p> }}>
      <Component />
    </MDXProvider>
  );
};
@ProchaLu
Copy link
Contributor

@Kuan-Ying Thanks for this!!

I will open a PR for this for @kentcdodds to review

Copy link

🎉 This issue has been resolved in version 10.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants