如何将标记文件加载到反应组件中?

我要怎么装载。Md 标记文件成为一个反应组件?我已经尝试了这么多的 npm 库通过谷歌搜索,我不能找到一个好的解决方案。

Code image

我想加载. md 文件,比如:

render() {
<div>
<MarkDown src="about.md" />
</div>
}
72549 次浏览

我使用 标记(GitHub)。

我首先像这样导入它:

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>
)
}

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

Markdown-to-jsx 提供了非常有效的功能来与 React 组件中的 markdown 交互。

它允许用用于标记的自定义组件 医生来了替换/重写任何 HTML 元素。

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

编辑1921年8月2日

功能组件
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>
)
}

如果您使用 Webpack (即 电子反应样板) ,那么您可以通过使用 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 将在导入标记文件时报告一个错误(它仍然可以工作)。把这个加到。Flowconfig 使 Flow 将 md 文件视为字符串资产(由 Webpack 负责) :

module.name_mapper.extension='md' -> '<PROJECT_ROOT>/internals/flow/WebpackAsset.js.flow'

您应该使用 反应减价而不是 接受的答案,这个解决方案不使用 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;

应用

# React & Markdown App
* Benefits of using React... but...
* Write layout in Markdown!

我已经尝试了上面的建议,并推断在运行命令之后

> npm install markdown
import ReactMarkdown from 'markdown';

我终于成功了

对于 打字稿 + 反应,请遵循以下步骤:

  1. 在一个项目目录中创建一个 类型定义(Index.d.ts)文件,并放入以下代码。
declare module "*.md";
  1. 按以下方式添加 tsconfig.json -> CompilerOptions -> typeRoots
{
"compilerOptions": {
...
"typeRoots": [ "<types-directory-created-in-#1>", "./node_modules/@types"],
...
}
}
  1. 安装两个库 摊牌Html-response-parser 反应-解析器

yarn add showdownnpm install showdown

yarn add html-react-parsernpm install html-react-parser

  1. 在你的组件里
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>
)
}

我稍微修改了这个 解决方案,使用了钩子和 useEffect(它不同于 componentWillUpdate,但仍然可以工作)。如果你使用 create-response-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 加载程序的方法

安装 原料装载机

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;

类似于@邢韩露的回答,但是带有反应降价。这个概念使用 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} />
</>
);
}

我希望它使用 反应减价动态导入工作。我的 将军代码如下,你需要添加一个 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);中添加空字符串(呵呵)。我从 给你上看到的。我不知道为什么会有用。

另一种选择是将 Markdown 放在。Js 文件,使用反勾‘字符将 Markdown 作为未标记的模板文本封装起来。像这样:

const MD = `
**TERMS OF SERVICE**


Last Modified: 30 November 2021...`


export default MD

然后你可以 import它像任何其他模块。

我纠结于所有这些答案的地方是将减记文件加载到前端 React 中。他们对你用的东西做了一些假设。

对于世界的反应,我会推荐 MDX

我在 Next.js 中使用它,但是 MDX 是 与许多 Javascript 捆绑包和 React 库兼容,并且做了大量的工作来处理很多人忽略的位,即加载非 JS 语法。

注意: MDX 更加坚持 Markdown 的原始风格,没有表格,也没有时髦的附加功能。如果你想要额外的东西,你需要安装 MDX 插件

参见下面的参考文献:

安装:

npm install @next/mdx @mdx-js/loader

返回文章页面

对于 Next.js 集成,我们不必触摸 webpack 配置,只需用 withMDX函数包装我们现有的 next.config.js:

/**
* @link https://github.com/vercel/next.js/tree/canary/packages/next-mdx#usage
*/
const withMDX = require('@next/mdx')()


// your existing next.config.js
const nextConfig = {
...
}


module.exports = withMDX(nextConfig)

返回文章页面

阅读更多关于 使用 MDX 文档的内容

# Just some regular markdown


any old rubbish **will do**


You can stick extra <Funky /> stuff in here but *regular markdown* works fine

返回文章页面

请注意,现在您不需要执行任何 fetching 或 useEffect操作,这就像加载 JSON 或 JS 文件一样简单。

import React from "react";
import AboutMarkdown from "./about.mdx";


const AboutPage () => (
<AboutMarkdown />
);

https://stackoverflow.com/a/42928796/12271495的更新版本

import React, { Component } from "react";
import { marked } from "marked";


class App extends Component {
state = {markdown: ""}
componentDidMount() {
const readmePath = require("./blogs/README.md");


fetch(readmePath)
.then((response) => {
return response.text();
})
.then((text) => {
this.setState({
markdown: marked.parse(text),
});
});
}


render() {
const { markdown } = this.state;


return (
<section>
<article dangerouslySetInnerHTML=\{\{ __html: markdown }}></article>
</section>
);
}
}


export default App;