Ben
Ben

Reputation: 16689

Dynamically loading Markdown file in React

I use markdown-to-jsx to render markdown in my React component.

My problem is that I want to dynamically load the markdown file, instead of specifying it with import. The scenario is that this happens on an article details page, i.e. I get the articleId from the route params and then based on that id, I want to load the corresponding markdown file, e.g. article-123.md.

Here's what I have so far. How can I load the md file dynamically?

import React, { Component } from 'react'
import Markdown from 'markdown-to-jsx';
import articleMd from './article-123.md'

class Article extends Component {
  constructor(props) {
    super(props)
    this.state = { md: '' }
  }

  componentWillMount() {
    fetch(articleMd)
      .then((res) => res.text())
      .then((md) => {
        this.setState({ md })
      })
  }

  render() {
    return (
      <div className="article">
        <Markdown children={this.state.md}/>
      </div>
    )
  }
}

export default Article

This works fine as is, but if I remove import articleMd from './article-123.md' at the top and instead pass the file path directly to fetch it output what looks like index.html, not the expected md file.

Upvotes: 5

Views: 6292

Answers (2)

Emiliano Penaloza
Emiliano Penaloza

Reputation: 11

I know this is an old thread but I just solved this issue with the following code using markdown-to-jsx

import React, { Component } from 'react'
import Markdown from 'markdown-to-jsx'

    class Markdown_parser extends Component {
        
        
      constructor(props) {
        super(props)
        
        this.state = { md: "" }
      }
    
      componentWillMount() {
        const { path } = this.props;
        import(`${path}`).then((module)=>
        
        fetch(module.default)
          .then((res) => res.text())
          .then((md) => {
            this.setState({ md })
          })
        )
      }
    
      render() {
    
        let { md } = this.state
    
        return (
          <div className="post">
            <Markdown children={md} />
          </div>
        )
      }
    }
    
    export default Markdown_parser

I then call the class sa follows

<Markdown_parser path = "path-to-your-fle" />

Upvotes: 1

zhuber
zhuber

Reputation: 5534

Can't you use dynamic import?

class Article extends React.Component {
    constructor(props) {
        super(props)
        this.state = { md: '' }
    }

    async componentDidMount() {
        const articleId = this.props.params.articleId; // or however you get your articleId
        const file = await import(`./article-${articleId}.md`);
        const response = await fetch(file.default);
        const text = await response.text();

        this.setState({
            md: text
        })
    }

    render() {
        return (
            <div className="article">
                <Markdown children={this.state.md} />
            </div>
        )
    }
}

Upvotes: 4

Related Questions