【发布时间】:2017-08-13 04:51:51
【问题描述】:
如何将 .md 降价文件加载到反应组件中?我通过google搜索尝试了很多npm库,但我找不到一个好的解决方案。
我想加载 .md 文件,例如:
render() {
<div>
<MarkDown src="about.md" />
</div>
}
【问题讨论】:
如何将 .md 降价文件加载到反应组件中?我通过google搜索尝试了很多npm库,但我找不到一个好的解决方案。
我想加载 .md 文件,例如:
render() {
<div>
<MarkDown src="about.md" />
</div>
}
【问题讨论】:
我首先是这样导入的:
import marked from "marked";
然后我在 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)
})
})
}
...最后我使用dangerouslySetInnerHTML 属性在页面上呈现它:
render() {
const { markdown } = this.state;
return (
<section>
<article dangerouslySetInnerHTML={{__html: markdown}}></article>
</section>
)
}
【讨论】:
npm install marked --save 应该可以解决问题。
dangerouslySetInnerHTML 属性。
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
【讨论】:
Cannot find module './Terms.fr.md' or its corresponding type declarations 错误。使用const termsFrPath = require './Terms.fr.md' 有效。
您应该使用react-markdown 而不是accepted answer,此解决方案不使用dangerouslySetInnerHTML。
App.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!
【讨论】:
Module parse failed: Unexpected token (1:4)
markdown-to-jsx 提供了非常高效的功能来与 React 组件中的 markdown 进行交互。
它允许用您的自定义组件替换/覆盖任何 HTML 元素以用于降价,here is the 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>
)
}
【讨论】:
类似于@Xing-Han-Lu 的回答,但对 Markdown 有反应。该概念使用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} />
</>
);
}
【讨论】:
安装 raw-loader
npm install raw-loader --save-dev
更新 webpack.config.js
module.exports = {
//...
module: {
rules: [
// ...
{
test: /\.md$/,
use: "raw-loader",
},
],
},
};
创建降价文件(比如App.md)
# React & Markdown App
- Benefits of using React... but...
- Write layout in Markdown!
导入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;
【讨论】:
对于 Typescript + react,请按照以下步骤操作:
declare module "*.md";
tsconfig.json -> CompilerOptions -> typeRoots如下{
"compilerOptions": {
...
"typeRoots": [ "<types-directory-created-in-#1>", "./node_modules/@types"],
...
}
}
yarn add showdown 或 npm install showdown
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>
)
}
【讨论】:
我稍微修改了这个solution 以使用钩子和useEffect(这与componentWillUpdate 不同,但仍然有效)。如果您使用 create-react-app 构建了您的应用,并且您有一个名为 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;
【讨论】:
如果您使用 Webpack(即Electron React Boilerplate),那么您可以通过使用 Webpack 加载器来节省几个步骤。
npm i -D html-loader markdown-loader marked
在 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
}
}
]
}
然后,在 React 组件中,它只是一个要求和设置 HTML。
import knownIssues from '../assets/md/known-issues.md';
....
<p dangerouslySetInnerHTML={{ __html: knownIssues }} />
最后,Flow 会在导入 markdown 文件时报错(仍然有效)。将此添加到 .flowconfig 以使 Flow 将 md 文件视为字符串资产(由 Webpack 负责):
module.name_mapper.extension='md' -> '<PROJECT_ROOT>/internals/flow/WebpackAsset.js.flow'
【讨论】:
我已经尝试了上述建议,并在运行命令后推断出
> npm install markdown
import ReactMarkdown from 'markdown';
它终于对我有用了
【讨论】:
我希望它使用 react-markdown 使用动态导入来工作。我的 general 代码如下,您必须添加一个 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);
}
};
const readmePath = await require("" + location); 中需要添加空字符串 (hehe)。我是从here 那里得到的。我不知道它为什么有效。
【讨论】:
另一种选择是将 Markdown 放在 .js 文件中,使用反引号 ` 字符将 Markdown 作为未标记的模板文字括起来。像这样:
const MD = `
**TERMS OF SERVICE**
Last Modified: 30 November 2021...`
export default MD
然后你可以像任何其他模块一样import它。
【讨论】: