Closed craigmcginley closed 6 years ago
gatsby-mdx 0.2.0
I ran into this too yesterday after trying to migrate from my custom private plugin (waited for gatsby-mdx to be more stable and mature, now it includes more features than my implementation).
I checked the source and I think this is related to the latest changes like #123 regarding the usage of the MDXRenderer
component along with the componentWithMDXScope
function to inject the data from within GraphQL. Unfortunately the docs haven't been updated so new users will run into this.
You're using the componentWithMDXScope
function in your gatsby-node.js
, but passes the children
in the posts-page-layout.js
instead of the data from a GraphQL query in combination with the MDXRenderer
component.
Check out the demo repo ChristopherBiscardi/gatsby-mdx-minimal-repro to see how to use the new feature.
I'm a bit confused since #123 isn't merged yet.
Either way, I still can't get that to work. Gatsby tells me the GraphQL query from a non-page (in this case, the posts-page-layout.js
component) won't be run. I tried using StaticQuery inside the component instead, but GraphQL says no $id
was passed in. I'm not sure where that id
is configured/passed other than in gatsby-node.js, which I have.
Am I missing something?
You can ignore these warnings: The GraphQL query in the non-page component "...src/templates/x-page.js" will not be run.
gatsby-mdx does actually run pageQueries. But it does not yet re-evaluate them for us, so hot reloading of the md(x) content doesn't work. Here is a minimal example that I've got working:
class SomePage extends React.Component {
render() {
const mdx = this.props.data.mdx
return (
<MDXRenderer>{mdx.code.body}</MDXRenderer>
)
}
}
export default SomePage
export const pageQuery = graphql`
query($id: String!) {
mdx(id: { eq: $id }) {
code {
body
}
}
}
`
@craigmcginley It looks like you're trying to use an "mdx layout" (which does use children) as a gatsby page layout (which has no children).
The component for a page needs to look more like this one. Especially note the MDXRenderer and the pageQuery usage.
import React from 'react'
import { graphql } from 'gatsby'
import MDXRenderer from 'gatsby-mdx/mdx-renderer'
import { MDXProvider } from '@mdx-js/tag'
import Header from './header'
export default ({ data }) => (
<MDXProvider components={{}}>
<Header siteTitle={data.site.siteMetadata.title} />
<MDXRenderer>{data.mdx.code.body}</MDXRenderer>
</MDXProvider>
)
export const pageQuery = graphql`
query($id: String!) {
site {
siteMetadata {
title
}
}
mdx(id: { eq: $id }) {
id
code {
body
}
}
}
`
componentWithMDXScope is a bit confusing if you don't know what it does, but it's safe to treat it mentally as the same as passing in the gatsby page layout path. It injects the mdx scope in a wrapper component and then uses that component as the page layout instead, but it's transparent and you should never have to deal with it. The page layout you use still needs to query the content it wants to render, as typical of gatsby apps.
Thanks @rdrey and @ChristopherBiscardi. Had to step away for a bit but I think I have things set up correctly now. Yet using components through MDXProvider
does not seem to work. Check out this example using the gatsby-mdx-minimal-repro:
https://github.com/craigmcginley/gatsby-mdx-provider
Try going to page 3 and you'll see the component I'm trying to reference is undefined.
Could be related to https://github.com/mdx-js/mdx/issues/206
Should I open a new gatsby-mdx issue for this?
I haven't been able to pass in components like that either, I've been using import statements at the start of my .mdx
files. (After making them globally accessible with https://github.com/craigmcginley/gatsby-mdx-provider/blob/master/gatsby-node.js#L50)
Excellent. Thanks so much @rdrey!
@craigmcginley The approach in https://github.com/craigmcginley/gatsby-mdx-provider/commit/563a00ee4d9901c780591db2acf3f7e1bcb527dd is unsupported. If you use a component in an MDX file, you have to import it to use it.
MDXProvider
works by allowing you to take control of rendering for primitive tags like <div>
, <a>
, <p>
, etc. It does not allow you to define new elements and use them in MDX files.
The issue that would support global usage of components without explicitly importing them is #138
That would be a useful feature for gatsby-mdx @ChristopherBiscardi. And it appears I misinterpreted the mdxjs docs here: https://mdxjs.com/getting-started/#example-usage
I imagined inlineCode
was a custom component but is actually probably just inline code elements ;)
@craigmcginley ah, of course. I was confused about a similar thing when I started getting involved with mdx. There are two non-primitives that you can replace, inlineCode
and wrapper
. These are created by the HAST transformations and the transformation to JSX in mdx core. inlineCode
represents inline code and wrapper
is the wrapping element containing all of the MDX.
Describe the bug When trying to render
this.props.children
(the markdown content from file) in my layout component, it's coming in asundefined
. I could be in error, but check my playground project. LMK if you need assistance updating the docs anywhere as well.To Reproduce https://github.com/craigmcginley/gatsby-mdx-children
yarn develop
Expected behavior Markdown file content should be visible, but it is not