# Using React components in Markdown source #312

Closed
opened this Issue Jun 5, 2016 · 112 comments

Projects
None yet

### cutemachine commented Jun 5, 2016

 Is there an easy way to use React components in my Markdown source. Something like reactdown?
Contributor

### ivanoats commented Jun 6, 2016

 That is a great idea. I would be willing to work on if it's not available yet.

### andreypopp commented Jun 6, 2016

 I the developer of reactdown. It would be awesome to see reactdown working with Gatsby. Ping me if you have questions or need some assistance regarding integrating it.
Contributor

### KyleAMathews commented Jun 6, 2016

 👍 this is a common request so would be great to have something working that's widely available!
Member

### benstepp commented Jun 8, 2016

 I set up a quick and dirty example repository of how to get reactdown working with gatsby. It's good to note that under the hood gatsby is just a very user friendly wrapper on top of webpack, so all of the power is still there to do just about anything. https://github.com/benstepp/gatsby-reactdown
Author

### cutemachine commented Jun 8, 2016

 Thanks, I will try it and will let you know how it went.
Contributor

### KyleAMathews commented Jun 8, 2016

 Oh cool! Nice Ben. That's a lot simpler to setup than I'd been imaging haha. Nice work Andrey. On Tue, Jun 7, 2016 at 10:31 PM Jo Meenen notifications@github.com wrote: Thanks, I will try it and will let you know how it went. — You are receiving this because you commented. Reply to this email directly, view it on GitHub #312 (comment), or mute the thread https://github.com/notifications/unsubscribe/AAEVh-2doZe_FXFMBxYTJ5FAVqo4XqxNks5qJlO6gaJpZM4Iubim .
Contributor

### SachaG commented Sep 6, 2016 • edited

 @benstepp nice! This looks straightforward enough when using Markdown files through a wrapper, but would this also work when importing the markdown file to use inside a React component? Edit: it seems like it should just work out of the box, but somehow the React component the md file is transformed into doesn't output anything…
Contributor

### KyleAMathews commented Sep 6, 2016

 I'm been thinking about a different approach that the new GraphQL layer (#420) opens up. I opened an issue asking about it in the mdash repo syntax-tree/mdast#13
Contributor

### SachaG commented Sep 6, 2016

 That'd be awesome! I felt I was so close with Reactdown though… The markdown files are properly transformed into React components by webpack (at least it looks like it), but it just gives me empty components when I use them in my code.

### andreypopp commented Sep 6, 2016

 @SachaG have a repo somewhere I can took a look at?
Contributor

### SachaG commented Sep 8, 2016

 Wow, really weird. I was trying to create a reproduction of the issue, and now it works! Not even sure what changed… Can't complain I guess :)
Contributor

### emilyaviva commented Sep 8, 2016

 The gods of React came down in a golden chariot, and lo! the code worked

### andreypopp commented Sep 8, 2016

 @SachaG I remember there were some issues with how reactdown references its runtime. Anyway if you hit some issues I would be flat do help.
Contributor

### Piyush3dB commented May 2, 2017

 Hello! Has there been any recent updates to this? What is the recommended method of using react components in markdown? Is there an example I can follow? Thanks!
Contributor

### KyleAMathews commented May 2, 2017

 Not yet :-( I have a good plan for how to do it — basically compile the markdown file into a React component file where you handle importing correctly all the referenced React components but haven't needed to build it quite yet. Feel free to start working on it if you need it!
Contributor

### Piyush3dB commented May 2, 2017 • edited

 @KyleAMathews do you mean I should run a converter script on my markdown file and then manually add the other react components I need to the output file produced by the conversion step? Once this is done then do the final build?
Contributor

### KyleAMathews commented May 2, 2017

 This would ideally be a plugin for Gatsby v1 that would do these steps automatically. … On Tue, May 2, 2017, 12:50 PM Piyush Singh ***@***.***> wrote: @KyleAMathews do you mean I should run a converter script on my markdown file and then add the other react components I need to the output file produced by the conversion step? Once this is done then do the final build? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#312 (comment)>, or mute the thread .
Contributor

### KyleAMathews commented May 5, 2017

 A simple example of what I mean. Imagine you had a markdown file at /my-blog/index.md that looked like the following: --- title: "hi folks" --- # This is my broomstick Yo yo foo  The body could then get converted into a react component which would get run through webpack/babel/etc. as normal. import React from 'react' import SweetComponent from 'auto-resolve-this-somehow' class MarkdownBody extends React.Component { render () { return (

This is my broomstick

Yo yo foo

) } } The trick part is how to integrate this with Gatsby's graphql system. Ideally you could just query for the "component" version of a markdown file similar to how you can query for the html today. Anyways, that's a brief sketch of what I've thought about.
Contributor

### Piyush3dB commented May 5, 2017

 @KyleAMathews thanks, I think I get the idea now. My aim is to be able to write content like this which leverage MathJax, D3.js visualisations and could also incorporate Three.js animation components within the markdown source. If you see the html source here the page uses jQuery for some of the control sliders, though I imagine there might be better ways of doing jQuery stuff with React components? From what I gather so far, I imagine producing such content with the Gatsby framework is achievable in a much neater and structured way, is that right? I'm new to web development, but doing my best to learn how the Gatsby system works so that I can contribute to achieving these sorts of goals...
Contributor

### Piyush3dB commented May 10, 2017

 @KyleAMathews, I've been thinking about your proposed solution.. Do you think something like markdown-it-jsx could be used or improved upon to perform conversion to the desired MD JS component structure? For resolving auto-resolve-this-somehow part, perhaps a second parser could scan the MD JS component file to look for JSX that match those in a component registry list (which could be a simple text file or file look-up in the directory where all components will be stored) and then add the relevant import line to the top of the file? I'm going to start working on this so any feedback would be awesome!

### stereobooster commented May 13, 2017 • edited

 Just a note there is another project which is doing this, maybe it will be useful as reference: react-styleguidist. Example of markdown file Enabling components in markdown reminds me this masterpiece by Bret Victor. UPD: and one more example: mdxc And another one http://thejameskyle.com/react-markings.html

Closed

Contributor

### timsuchanek commented Jul 20, 2017

 A solution is using react-jsx-parser. At howtographql.com we're using it in production: https://github.com/howtographql/howtographql/blob/master/src/components/Tutorials/Markdown.tsx#L182 One disadvantage: It's of course slower than just using dangerouslySetInnerHTML, because it Parses the HTML Constructs a virtual dom tree Renders the virtual tree with React One way to speed this up would be to not send the raw html with the graphql query, but actually send a format that the Inferno.js docs are using, as described here. As I currently can't find the time to do this last step of optimization, anybody who is interested in it could go this approach. That would mean to Construct proper GraphQL Types, that shouldn't be a problem as GraphQL Types can be recursive and represent a tree After the remark markdown parsing business is done, generate a serialized jsx format. In React deserialize this format.
Contributor

### KyleAMathews commented Jul 25, 2017

 Another option I've been eyeing is https://github.com/mapbox/jsxtreme-markdown We could use a similar pattern. Just convert markdown to JSX components. Use custom delimiters to add JavaScript and JSX. We could use our existing Remark setup just fine. And there wouldn't be much of a performance penalty as it'd just be normal React pages.
Member

### ChristopherBiscardi commented Jul 26, 2017

 There is also https://github.com/cerebral/marksy, which I used recently to good effect.

### lindekaer commented Aug 31, 2017

 Is there a recommended approach for this in the context of Gatsby or is it still to be decided?

### revolunet commented Sep 15, 2017

 Hi, any recommendation to include customs components in our gatsby markdown files ?

### stereobooster commented Sep 15, 2017

 One more option into the collection https://idyll-lang.github.io/

### revolunet commented Sep 22, 2017 • edited

 Looks like marksy works nicely for that use case as it returns a react elements tree, i'm wondering how i could integrate that into a gatsby plugin ?

### abdulhannanali commented Oct 1, 2017

 @KyleAMathews @revolunet What do you think about registering the components we need to use as custom elements, afterwards we can simple include them within the blog post and leave the rest of the work for browser to do? This would eliminate any need to parse markdown as a react tree and keep our application performant, however, I don't know if there's going to be a performance cost, to do ReactDOM.render each time we need to add a new custom components, but still it would give us a pretty cool way to add dynamic functionality to the blog posts.

### silvenon commented Jul 9, 2018

 Oh, I just read the comments above, the trick is that Gatsby v1 automatically wraps everything in a layout component, so you're using absolutePath to target the MDX file. 😃 Thanks for this trick!

Open

Closed

Contributor

### timsuchanek commented Jul 14, 2018

 @avigoldman any news on the Gatsby 2 plugin? It would also be awesome if you could give rough directions on how you would build it without the layout component that doesn't exist in Gatsby 2 anymore. Thanks!

### silvenon commented Jul 14, 2018

 I was hoping I could somehow use the export default feature of MDX, but passing any additional props other than children doesn't seem to be possible ATM. mdx-js/mdx#187

### silvenon commented Jul 15, 2018

 If my PR gets merged (mdx-js/mdx#189), I think we'll be able to use MDX with existing gatsby-plugin-mdx and gatsby-transformer-mdx. The only required change will be on our end, and that's exporting our post template from our .mdx files: src/posts/hello-world.mdx: import Post from '../components/post' # Hello World Lorem ipsum. export default Post  gatsby-node.js: const path = require('path') exports.createPages = ({ actions }) => { actions.createPage({ path: '/posts/hello-world', component: path.join(__dirname, 'src', 'posts', 'hello-world.mdx'), context: { /* passed as pageContext */ } }) } src/components/post.js: import React from 'react' import Layout from './layout' export default ({ children, pageContext }) => ( {children} )

### DylanVann commented Jul 19, 2018

 I think this is really critical. Right now all the gatsby-remark-* plugins are ~reimplementing a bunch of rendering logic that could and probably should be in React. This could simplify things a lot.
Contributor

### KyleAMathews commented Jul 19, 2018

 @DylanVann that kinda depends. gatsby-remark-* plugins do a lot of build-time transformations that if we did those in React would mean shipping a lot of JS to browsers. Also things that are impossible to do in React like https://www.gatsbyjs.org/packages/gatsby-remark-images/?=remark-image
Contributor

### KyleAMathews commented Jul 19, 2018

 Ideally of course we blend the both of both worlds.

### DylanVann commented Jul 19, 2018

 @KyleAMathews Yeah it would mean some more JS on the client side, although it would still be first delivered as static HTML. I think a lot of people are probably shipping gatsby-image for some parts of their site anyways, so in that case duplication is less of an issue. I do understand that there is utility in the gatsby-remark-* plugins. The rendering logic specifically, which is currently done with strings, seems like it could be done in React though. I've got this sort of working with the htmlAst/rehype-react method.

### silvenon commented Jul 19, 2018

 It seems that way, but in practice it's much more complicated. If you believe you're onto something, you could raise a new issue with a focused proposition.

### DylanVann commented Jul 19, 2018 • edited

 It seems like a hard problem to solve. Unfortunately I don't think I'll have time to implement anything or make a proposal. The idea of doing remark plugins partially using React custom components definitely works, I have code using it. This is generated by @dylanvann/gatsby-remark-cloudinary from markdown images ending in mp4. The idea is to optimize videos (sizing at build time, adding posters). I wanted the rendering logic in React though. Processing of the video is done in another function but this is part of what the node's HTML is replaced with. export const videoHTML = ({ srcVideo, srcVideoPoster, base64, paddingBottom, presentationWidth, }) =>  Then using a custom component with rehype-react. import React from 'react' import rehypeReact from 'rehype-react' import CloudVideo from './CloudVideo' const renderAst = new rehypeReact({ createElement: React.createElement, components: { 'cloud-video': CloudVideo, }, }).Compiler const Markdown = ({ ast }) => renderAst(ast) Markdown.propTypes = { ast: PropTypes.object, } export default Markdown The ast can be pulled out of GraphQL. So this component works for SSR and client side. Anyways I know how it is with OSS. I'm just saying I think it would be a great feature and could reduce code complexity, so it would be great if anyone has time to figure out better solutions.

### silvenon commented Jul 19, 2018 • edited

 I'm not disagreeing with anything you are saying, I think that starting a good discussion would be much better in its own issue, rather than at the end of a very loaded thread of 60+ comments. 😉

Merged

Member

### ChristopherBiscardi commented Jul 26, 2018

 Me and @avigoldman built gatsby-mdx to house ambitious 2.0 compatible MDX integrations and utils. Currently gatsby .mdx pages work by default after enabling the plugin and the following additional features have been added on top of mdx: Use and query classic and JSON style frontmatter Define default layouts for mdx files that don't define one We're also planning more sophisticated integrations for advanced image processing custom md and hast plugins. compatibility with all the same fields as gatsby-transformer-remark We're still pretty early in the lifecycle, so let us know if you run into any issues and we'll get it done :)

### silvenon commented Jul 26, 2018 • edited

 @ChristopherBiscardi is it meant to be used in combination with gatsby-plugin-mdx or instead of it?
Member

### ChristopherBiscardi commented Jul 26, 2018

 @silvenon It looks like gatsby-plugin-mdx will be deprecated and thus stop at 1.0, while gatsby-mdx will move forward with 2.0 and beyond.
Contributor

### avigoldman commented Jul 31, 2018

 @m-allanson think its safe to close this issue now that we have gatsby-mdx?
Member

### m-allanson commented Jul 31, 2018

 I think so, thanks everyone 🎉

Open

Contributor

### janosh commented Aug 28, 2018 • edited

 So is gatsby-mdx now to be preferred over rehype-react in conjunction with gatsby-transformer-remark as described here? If the answer is not a clear-cut yes, could someone explain the advantages and drawbacks of both approaches?

### silvenon commented Aug 28, 2018 • edited

 I think this part of that blog post answers your question. rehype-react provides custom HTML elements which map to React components, but MDX actually is JSX inside Markdown, it's more predictable and has less caveats. I'm not in the Gatsby team, but I would say yes, gatsby-mdx is the preferred way of React in Markdown.
Contributor

### CanRau commented Aug 28, 2018

 @janosh as far as I know gatsby-mdx can't replace gatsby-transformer-remark completely yet seems to still miss gatsby-remark-images & gatsby-remark-copy-linked-files for example and other gatsby-remark plugins.. I think they're working on it but not sure about the current state But if you're not in the need of those plugins or can wait then I would say yes, at least I'll prefer it, seems cleaner to me
Member

### ChristopherBiscardi commented Aug 28, 2018

 @CanRau I'm rebasing that today (ChristopherBiscardi/gatsby-mdx#68) with the intent to merge and release. There will probably be some edge cases we have to deal with but I'll be going over some of them today on stream before I merge. The state of the PR is that gatsby-remark-* plugins are applied properly, but there are differences in how the output of say, the gatsby-remark-prismjs plugin (which currently produces HTML output) is handled by transformer-remark vs mdx's pipeline. I view support for plugins like gatsby-remark-prismjs as important, but also a suboptimal approach. A better approach in the MDX world is to use something like prism-react-renderer as the code element in an MDXProvider, which would give you full flexibility and control over the rendering when compared to using remark plugins to achieve a similar effect (and also allow you to share that component with non-mdx content like .js pages). I'm far more concerned with the copy-linked-files and image processing working than I am with prismjs working for the first release of gatsby-remark-* plugin support.
Contributor

### CanRau commented Aug 28, 2018

 Sounds awesome @ChristopherBiscardi especially copy-linked-files and image support, I would love to help but realistically speaking I don't think I can handle it right now as we're really packed^^ Maybe I can share some feedback, I think I'll give it a try for some smaller meta pages to try things out interesting to know that you're streaming your work..I'm quite new to live stuff and don't yet understand how to know when you're going life..probably works only with an account I guess
Member

### ChristopherBiscardi commented Aug 28, 2018

 Happy to have you help at any point in the future if you find the time, feel free to ping me if you have questions :) Feedback itself helps a bunch either way though so if you try it out be sure to file issues! interesting to know that you're streaming your work..I'm quite new to live stuff and don't yet understand how to know when you're going life..probably works only with an account I guess I set up a "calendar" of streaming times at the bottom of my twitch channel. I know if someone has a twitch account and they follow me they'll get notifications when I go live, but otherwise the schedule is where to look. Pretty sure you can watch whether you have an account or not. I'm a bit new to streaming myself (only been doing it a couple weeks now) so always open to better ways to do this kind of stuff. I've had a few people come around repeatedly and hang out/watch/talk in chat which is pretty fun :)
Contributor

### CanRau commented Aug 28, 2018

 kay got it, good to know and I'll surely post issues when I encounter any ;)

### silvenon commented Aug 28, 2018

 Btw, since Prism was mentioned, I'd just like to add that ideally remark/rehype plugins should be used directly, MDX supports that via mdPlugins and hastPlugins options (this can be passes through gatsby-mdx). Plugins like @mapbox/rehype-prism can be added to hastPlugins, but there were some whitespace issues that I fixed in mdx-js/mdx#226, so once that gets merged and released, syntax highlighting will be good to go!
Member

### ChristopherBiscardi commented Aug 29, 2018

 yeah, totally. gatsby-mdx already supports passing remark/rehype plugins through to mdx core. Here's @mapbox/rehype-prism for example (I yanked that example from some of your PR/Issue discussions originally @silvenon, thanks). AFAIK rehype prism doesn't support prism plugins so it's always a tradeoff depending on use cases (I believe using rehype plugins for prism means you will have a harder time integrating something like react-live, for example) gatsby-remark-prismjs and other gatsby-remark-* plugin support was released in 0.1.1 today, so now there's at least 3 options for syntax highlighting between rehype/remark/react-components 😝