83

I have my documentation written in markdown and I would like to render those files from my JSX (ES6+CommonJS) code into React components. How can I achieve this?

For example I have styles.markdown and I would like to render it into a <p> tag.

5
  • 1
    Are you using Browserify? Commented Aug 7, 2015 at 11:46
  • Yes I am using browserify Commented Aug 7, 2015 at 11:53
  • Are you using Babel as well? What do you mean by having styles.markdown? Commented Aug 7, 2015 at 12:06
  • Yep babel too. styles.markdown is just an example of markdown file Commented Aug 7, 2015 at 12:08
  • I'm not sure what you're trying to do here. You want to have something that renders react components to markdown? Commented Aug 7, 2015 at 12:49

5 Answers 5

114

You can use React-Markdown:

const React = require('react')
const ReactDOM = require('react-dom')
const ReactMarkdown = require('react-markdown')

const input = '# This is a header\n\nAnd this is a paragraph'

ReactDOM.render(<ReactMarkdown source={input} />, document.getElementById('container'))

Or... You can just create a simple React component that wraps a call to a Markdown parser. There are two very good ones for JavaScript:

Now, you can create a component like this:

var MarkdownViewer = React.createClass({
    render: function() {
        // pseudo code here, depends on the parser
        var markdown = markdown.parse(this.props.markdown);
        return <div dangerouslySetInnerHTML={{__html:markdown}} />;
    }
});

There used to have one already, but it doesn't seem to be maintained anymore: https://github.com/tcoopman/markdown-react

Also, if you need a React Markdown Editor, check out: react-mde. Disclaimer: I am the author.

Sign up to request clarification or add additional context in comments.

4 Comments

Not sure when this changed, but I was working through it today and React appears to now require an object with an __html field rather than just a string (e.g. dangerouslySetInnerHTML={{__html: markdown}}). Also, even though it might not be relevant to the question asked here, it is worth noting that one is well advised to have the markdown library sanitize the input to avoid XSS, if any of it is potentially untrusted (e.g. var markdown = marked.parse(this.props.markdown, {sanitize: true});).
Thanks @GrandOpener. I've updated the answer accordingly.
Is dangerouslySetInnerHTML inefficient when the component re-renders?
It looks like source={...} is obsolete. In the current version it is - <ReactMarkdown children={ ... }/>
39

The package react-markdown with Markdown component will be good choice:

import React from 'react'
import Markdown from 'react-markdown'
    
var src = "# This is markdown document"
    
React.render(
  <Markdown children={src} />,
  document.getElementById('root')
)

You can write inplace here-docs like this:

<Markdown>
  # Header

  * dotted lists
  * [url](/doc)
</Markdown>

It is possible to specify transformers for link-urls and image-urls and much more.

4 Comments

I agree with @Oklas. react-markdown is probably the best solution. I just started using it myself. However, be careful of how and which quotes or back ticks you use. If you write in es6 and beyond, code snippets can cause problems. For example, I had to transpile es6 into es5 (used babel transpiler on their site for speed and precision) in order to remove errors I was getting like "undefined". Just beware that there are a few challenges here and there regarding syntax that you have to figure out workarounds for.
And this is the discussion thread I had earlier today with the plugin's creator regarding the issue: github.com/rexxars/react-markdown/issues/91 rexxars was fast to respond and extremely helpful!
This is pretty good but i am having some issue with this for some reason html tags do not work when passing markdown as strings is that how it is supposed to work because in there demo i saw them using html tags but it does not seem to work for me the markdown stuff is working okay though
One thing I ran into: You can't import a .md file in javascript unless you have the proper loader, but you can easily put the markdown into a string and import it that way.
14

I'm a little late to the party, but I wrote a competitor library to the ones mentioned above that has an added benefit of not needing the dangerouslySetInnerHtml hack: https://github.com/probablyup/markdown-to-jsx

1 Comment

I tried both react-markdown and markdown-to-jsx today. Long story short: markdown-to-jsx is 5 times lighter, and it was much easier to configure it to open _blank links with safe noopener defaults. See github.com/probablyup/markdown-to-jsx/issues/… (I basically didn't success at doing that with react-markdown)
12

Example of Markdown component that renders html from markdown text, the logic of loading data should be implemented in separate store/parent component/whatever. I am using marked package for converting markdown to html.

import React from 'react';
import marked from 'marked';

export default class MarkdownElement extends React.Component {
  constructor(props) {
    super(props);

    marked.setOptions({
      gfm: true,
      tables: true,
      breaks: false,
      pedantic: false,
      sanitize: true,
      smartLists: true,
      smartypants: false
    });
  }
  render() {
    const { text } = this.props,
      html = marked(text || '');

    return (<div>
      <div dangerouslySetInnerHTML={{__html: html}} />
    </div>);
  }
}

MarkdownElement.propTypes = {
  text: React.PropTypes.string.isRequired
};

MarkdownElement.defaultProps = {
  text: ''
};

Comments

7

Try something like this:

import fs from 'fs';
import React, { Component, PropTypes } from 'react';

class Markdown extends Component {
    constructor() {
        super(props);
        this.state = { contents: '' };
        this.componentDidMount = this.componentDidMount.bind(this);
    }

    componentDidMount() {
        const contents = fs.readFileSync(this.props.path, 'utf8');
        this.setState({ contents });
    }

    render()
        return (
            <div>
                {this.state.contents.split('\n').map((line, i) =>
                    line ? <p key={i}>{line}</p> : <br key={i} />)}
            </div>
        );
    }
}

Markdown.propTypes = { path: PropTypes.string.isRequired };

React.render(<Markdown path='./README.md' />, document.body);

Or if you're using ES7+ features:

import fs from 'fs';
import React, { Component, PropTypes } from 'react';

class Markdown extends Component {
    static propTypes = { path: PropTypes.string.isRequired };

    state = { contents: '' };

    componentDidMount = () => {
        const contents = fs.readFileSync(this.props.path, 'utf8');
        this.setState({ contents });
    };

    render() {
        return (
            <div>
                {this.state.contents.split('\n').map((line, i) =>
                    line ? <p key={i}>{line}</p> : <br key={i} />)}
            </div>
        );
    }
}

React.render(<Markdown path='./README.md' />, document.body);

You'll need to use the brfs transform to be able to use fs.readFileSync if this is running client-side.

1 Comment

yeah. fs is a node module and won't work client side (at least as far as i know)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.