[英]How do I load a markdown file into a react component?
How would I load a .md markdown file into a react component?我如何将 .md 降价文件加载到反应组件中? I have tried so many npm libraries through google searches and I cant find a good solution.
我通过谷歌搜索尝试了很多 npm 库,但找不到好的解决方案。
I want to load the .md file something like:我想加载 .md 文件,例如:
render() {
<div>
<MarkDown src="about.md" />
</div>
}
I use marked ( GitHub ).我使用标记( GitHub )。
I first import it like this:我首先像这样导入它:
import marked from "marked";
I then fetch my *.md file within React's componentDidMount
event and store it in my component's state using marked(text)
(where text
is the response):然后我在 React 的
componentDidMount
事件中获取我的 *.md 文件并使用marked(text)
(其中text
是响应)将其存储在我的组件状态中:
componentDidMount() {
const readmePath = require("./Readme.md");
fetch(readmePath)
.then(response => {
return response.text()
})
.then(text => {
this.setState({
markdown: marked(text)
})
})
}
...and finally I render it on the page using the dangerouslySetInnerHTML
attribute: ...最后我使用
dangerouslySetInnerHTML
属性在页面上呈现它:
render() {
const { markdown } = this.state;
return (
<section>
<article dangerouslySetInnerHTML={{__html: markdown}}></article>
</section>
)
}
A full working example with react-markdown
:一个带有
react-markdown
完整工作示例:
import React, { Component } from 'react'
import ReactMarkdown from 'react-markdown'
import termsFrPath from './Terms.fr.md'
class Terms extends Component {
constructor(props) {
super(props)
this.state = { terms: null }
}
componentWillMount() {
fetch(termsFrPath).then((response) => response.text()).then((text) => {
this.setState({ terms: text })
})
}
render() {
return (
<div className="content">
<ReactMarkdown source={this.state.terms} />
</div>
)
}
}
export default Terms
You should use react-markdown instead of the accepted answer , this solution doesn't use dangerouslySetInnerHTML
.您应该使用react-markdown而不是接受的答案,此解决方案不使用
dangerouslySetInnerHTML
。
App.js应用程序.js
import React, { Component } from 'react';
import AppMarkdown from './App.md';
import ReactMarkdown from 'react-markdown';
class App extends Component {
constructor() {
super();
this.state = { markdown: '' };
}
componentWillMount() {
// Get the contents from the Markdown file and put them in the React state, so we can reference it in render() below.
fetch(AppMarkdown).then(res => res.text()).then(text => this.setState({ markdown: text }));
}
render() {
const { markdown } = this.state;
return <ReactMarkdown source={markdown} />;
}
}
export default App;
App.md应用程序
# React & Markdown App
* Benefits of using React... but...
* Write layout in Markdown!
markdown-to-jsx provides very efficeint functionality to interact with markdown in React component. markdown-to-jsx提供了非常有效的功能来与 React 组件中的 markdown 交互。
It allows replacing/overriding of any HTML element with your Custom Component for markdown, here is the doc .它允许使用您的自定义组件替换/覆盖任何 HTML 元素以进行降价, 这里是 doc 。
import React, { Component } from 'react'
import Markdown from 'markdown-to-jsx';
import README from './README.md'
class PageComponent extends Component {
constructor(props) {
super(props)
this.state = { md: "" }
}
componentWillMount() {
fetch(README)
.then((res) => res.text())
.then((md) => {
this.setState({ md })
})
}
render() {
let { md } = this.state
return (
<div className="post">
<Markdown children={md}/>
</div>
)
}
}
export default PageComponent
const PageComponent = ()=> {
let [ content, setContent] = useState({md: ""});
useEffect(()=> {
fetch(README)
.then((res) => res.text())
.then((md) => {
setContent({ md })
})
}, [])
return (
<div className="post">
<Markdown children={content.md}/>
</div>
)
}
Similar to @Xing-Han-Lu's answer but with react Markdown.与@Xing-Han-Lu 的回答类似,但使用 Markdown 反应。 The concept uses
useEffect
to load up the file then adds it to state using the useState
hook where it's accessible to reactMarkdown
该概念使用
useEffect
加载该文件,然后使用它添加到状态useState
钩它的访问reactMarkdown
import React, { useState, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import file from "./md/posts.md";
export default function () {
const [markdown, setMarkdown] = useState("");
useEffect(() => {
fetch(file)
.then((res) => res.text())
.then((text) => setMarkdown(text));
}, []);
return (
<>
<ReactMarkdown source={markdown} />
</>
);
}
For Typescript + react please follow below steps:对于Typescript + react,请按照以下步骤操作:
declare module "*.md";
tsconfig.json -> CompilerOptions -> typeRoots
as followingtsconfig.json -> CompilerOptions -> typeRoots
如下{
"compilerOptions": {
...
"typeRoots": [ "<types-directory-created-in-#1>", "./node_modules/@types"],
...
}
}
yarn add showdown
or npm install showdown
yarn add showdown
或npm install showdown
yarn add html-react-parser
or npm install html-react-parser
yarn add html-react-parser
或npm install html-react-parser
import React, { useEffect, useState } from 'react';
import showdown from 'showdown';
import parse from 'html-react-parser';
import readme from 'path/filename.md';
export default function ComponentName() {
const [html, setHTML] = useState("");
//Use componentDidMount(): if class based component to load md file
useEffect(() => {
fetch(readme)
.then(data => data.text())
.then(text => {
const converter = new showdown.Converter();
setHTML(converter.makeHtml(text));
})
}, []);
return (
<div>{parse(html)}</div>
)
}
I slightly modified this solution to use hooks and useEffect
(which is different from componentWillUpdate
but still works).我稍微修改这个解决方案,以使用钩子和
useEffect
(这是从不同的componentWillUpdate
但仍然有效)。 If you built your app with create-react-app and you have a markdown document called document.md
, you can build your app in the following way:如果您使用 create-react-app 构建您的应用程序并且您有一个名为
document.md
的降价document.md
,您可以通过以下方式构建您的应用程序:
import { useState, useEffect } from 'react';
import Markdown from 'markdown-to-jsx';
import mdDocument from './document.md';
const App = () => {
const [content, setContent] = useState("");
useEffect(() => {
fetch(mdDocument)
.then(res => res.text())
.then(md => { setContent(md) })
})
return (
<div><Markdown children={content} /></div>
)
}
export default App;
Install raw-loader安装原始加载器
npm install raw-loader --save-dev
Update webpack.config.js更新webpack.config.js
module.exports = {
//...
module: {
rules: [
// ...
{
test: /\.md$/,
use: "raw-loader",
},
],
},
};
Create markdown file (say App.md
)创建降价文件(比如
App.md
)
# React & Markdown App
- Benefits of using React... but...
- Write layout in Markdown!
Import App.md
and use it in React component.导入
App.md
并在 React 组件中使用它。
import React from "react";
import ReactMarkdown from 'react-markdown';
import AppMarkdown from './App.md';
function App() {
return (
<div>
<ReactMarkdown children={`${AppMarkdown}`} />
</div>
);
}
export default App;
If you use Webpack (ie Electron React Boilerplate ) then you can save a few steps by using Webpack loaders.如果您使用 Webpack(即Electron React Boilerplate ),那么您可以通过使用 Webpack 加载器来节省几个步骤。
npm i -D html-loader markdown-loader marked
In webpack.config.renderer.dev.js:在 webpack.config.renderer.dev.js 中:
import marked from 'marked';
const markdownRenderer = new marked.Renderer();
....
// Markdown
{
test: /\.md$/,
use: [
{
loader: 'html-loader'
},
{
loader: 'markdown-loader',
options: {
pedantic: true,
renderer: markdownRenderer
}
}
]
}
Then, in the React component it's simply a require and setting the HTML.然后,在 React 组件中,它只是一个 require 和设置 HTML。
import knownIssues from '../assets/md/known-issues.md';
....
<p dangerouslySetInnerHTML={{ __html: knownIssues }} />
Lastly, Flow will report an error (it still works) when importing the markdown file.最后,Flow在导入markdown文件时会报错(它仍然有效)。 Add this to .flowconfig to make Flow treat md files as string assets (care of Webpack):
将此添加到 .flowconfig 以使 Flow 将 md 文件视为字符串资产(Webpack 的注意事项):
module.name_mapper.extension='md' -> '<PROJECT_ROOT>/internals/flow/WebpackAsset.js.flow'
I have tried the above suggestions and deduced that after running a command我已经尝试了上述建议并在运行命令后推断出
> npm install markdown
import ReactMarkdown from 'markdown';
it finally worked for me它终于对我有用了
I wanted it to work using dynamic imports using react-markdown .我希望它使用react-markdown使用动态导入工作。 My general code is below, you'll have to add a useEffect to call the function and put a reference to the state variable in the function return:
我的一般代码如下,您必须添加一个 useEffect 来调用该函数并在函数返回中放置对状态变量的引用:
const [displayElement, setDisplayElement] = useState(null);
//Get markdown file
const fetchMarkdown = async (location) => {
console.log("MD location: ", location);
try {
//I figured out readmePath.default using print statements, left there in case
//someone wants them
const readmePath = await require("" + location);
//console.log(readmePath);
const response = await fetch(readmePath.default);
//console.log("response => ", response);
const text = await response.text();
//console.log(text);
// the state variable I am setting the markdown into, in my render function
// I have {displayElement}.
setDisplayElement(
<div className={styles.markdownContainer}>
<ReactMarkdown children={text} />
</div>
);
} catch (e) {
console.log("Markdown file: couldn't read =>", location, e);
}
};
The addition of the empty string in const readmePath = await require("" + location);
const readmePath = await require("" + location);
中空字符串的添加const readmePath = await require("" + location);
is required ( hehe ).是必需的(呵呵)。 I got that from here .
我从这里得到的。 I don't know why it works.
我不知道它为什么有效。
Another option is to put the Markdown in a .js file, using the backtick ` character to enclose the Markdown as an untagged template literal.另一种选择是将 Markdown 放在 .js 文件中,使用反引号 ` 字符将 Markdown 作为未标记的模板文字括起来。 Like this:
像这样:
const MD = `
**TERMS OF SERVICE**
Last Modified: 30 November 2021...`
export default MD
Then you can import
it like any other module.然后您可以像
import
任何其他模块一样import
它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.