Skip to content
🎉Launching MDX V1 → v0
MDX logoMDX v1.0.18
GitHub logo

Components

The MDX core library accepts a string and exports a JSX string. It uses a custom pragma which customizes the rendering of elements in Markdown and JSX.

Tranpilation

Consider the following MDX:

import MyComponent from './my-component'
export const author = 'Fred Flintstone'
# Title
<MyComponent />
Lorem ipsum dolor sit amet.

MDX core turns that text into roughly the following JSX to be consumed by your app:

import React from 'react'
import MyComponent from './my-component'
export const author = 'Fred Flintstone'
const layoutProps = { author }
export default MDXContent({ components, ...props }) => (
<wrapper {...props} {...layoutProps}>
<h1>Title</h1>
<MyComponent />
<p>Lorem ipsum dolor sit amet.</p>
</wrapper>
)
MDXContent.isMDXComponent = true

If the component mapping contains a p key, that will be used for Lorem ipsum dolor sit amet.. Otherwise a standard p tag is rendered (<p>Lorem ipsum dolor sit amet.</p>). This is what allows you to pull in existing components to style your MDX documents via the MDXProvider

Layout props

You’ll also notice that layoutProps is created based on your exports and then passed to the wrapper. This allows for the wrapper to use those props automatically for handling things like adding an author bio to the wrapped document.

isMDXComponent

If you need to check whether a React component has been created by MDX, all MDX components have a static property isMDXComponent:

import React from 'react'
import ChangeLog from '../changelog.mdx'
export default () => (
<div>
<p>Component type: {ChangeLog.isMDXComponent ? 'MDX' : 'Regular'}</p>
<ChangeLog />
</div>
)

MDXProvider

Caveats

Because MDXProvider uses React Context directly, it is affected by the same caveats. It is therefore important that you do not declare your components mapping inline in the JSX. Doing so will trigger a rerender of your entire MDX page with every render cycle. Not only is this bad for performance, but it can cause unwanted side affects, like breaking in-page browser navigation.

Avoid this by following declaring your mapping as a constant.

Updating the mapping object during application runtime

If you need to change the mapping during runtime, declare it on the componentʼs state object:

import React from 'react'
import { MDXProvider } from '@mdx-js/react'
import { Heading, Text, Pre, Code, Table } from './components'
export default class Layout extends React.Component {
state = {
h1: Heading.H1,
h2: Heading.H2,
// ...
p: Text,
code: Pre,
inlineCode: Code
}
render() {
return (
<MDXProvider components={this.state}>
<main {...this.props} />
</MDXProvider>
)
}
}

You can now use the setState function to update the mapping object and be assured that it wonʼt trigger unnecessary renders.

Edit this page on GitHub
Next:
Getting Started