Passing common prop to all components in MDX file, without adding the prop to each component

Viewed 380

I've got mdx files with components that need to be locale aware.

Lots of components. And they all need to be locale-aware.

In the .mdx files, I can change them from this:

<FirstDayOfMonth/>

to that:

<FirstDayOfMonth lang="fr"/>

But then I'd need to do it for every component in every .mdx file.

Is there a way to make a prop available to all components used in mdx?


I thought of passing it to the MDXRenderer, something like this:

<MDXProvider>
  <MDXRenderer lang={currentLang}>{body}</MDXRenderer>
</MDXProvider>

Or accessing the frontmatter from the components.

But both approaches are not documented and didn't give any results.

Better ideas?


per request, list of relevant dependencies:

  "dependencies": {
    "@mdx-js/mdx": "^1.6.22",
    "@mdx-js/react": "^1.6.22",
    "gatsby": "^3.6.2",
    "gatsby-plugin-copy-files-enhanced": "^1.1.1",
    "gatsby-plugin-mdx": "^2.11.0",
    "preact": "^10.5.13",
    "preact-render-to-string": "^5.1.19",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
}
1 Answers

You could add those props when passing the shortcodes to the MDXProvider by iterating through the map and returning new components with the default props injected.

import FirstDayOfMonth from 'path/to/FirstDayOfMonth';

const addProps = (components, defaultProps) => {
  const withProps = {};

  for (const [key, Component] of Object.entries(components)) {
    withProps[key] = (props) => <Component {...defaultProps} {...props} />
  }

  return withProps;
}

const shortcodes = { FirstDayOfMonth, SomeOtherComponent };

const Layout = ({ children }) => {
  const someDefaultProps = {
    lang: "fr",
    something: "else",
  };

  const shortcodesWithProps = useMemo(
    () => addProps(shortcodes, someDefaultProps),
    someDefaultProps
  );

  return (
        ...
        <>
          <MDXProvider components={shortcodesWithProps}>
            {children}
          </MDXProvider>
        </>
       ...
  );
};
Related