如何将降价文件加载到反应组件中?
Posted
技术标签:
【中文标题】如何将降价文件加载到反应组件中?【英文标题】:How do I load a markdown file into a react component? 【发布时间】:2017-08-13 04:51:51 【问题描述】:如何将 .md 降价文件加载到反应组件中?我通过google搜索尝试了很多npm库,但我找不到一个好的解决方案。
我想加载 .md 文件,例如:
render()
<div>
<MarkDown src="about.md" />
</div>
【问题讨论】:
【参考方案1】:我使用marked (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>
)
【讨论】:
尝试导入“标记”,Typescript 找不到声明文件 我不熟悉 TypeScript,但你需要先安装包。npm install marked --save
应该可以解决问题。
啊,发现我需要安装类型定义才能让 Typescript 满意。 npmjs.com/package/@types/marked。谢谢我的朋友
对我不起作用 ./src/pages/about.md 模块解析失败:/Users/me/myproject/src/pages/about.md 意外字符 '#' (1:0 ) 您可能需要适当的加载程序来处理此文件类型。 SyntaxError: 意外字符 '#' (1:0)
查看***.com/a/53975297/7784399 而不是这个。它不使用dangerouslySetInnerHTML
属性。【参考方案2】:
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'
有效。【参考方案3】:
您应该使用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)
我认为您需要在其他地方添加您必须拥有的东西,以便像 JS 文件一样将 MD 文件作为导入处理
@ToniLeigh 能否提供步骤
@Coderboi 加载程序?你的意思是?包管理器? NPM。
当您不在 raw-loader 中将“.md”扩展名列入白名单时会出现问题,(是的,npm 包 raw-loader)...把它放在 webpack 中解决了我的问题。【参考方案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
21 年 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>
)
【讨论】:
这会产生:找不到模块:无法解析'./README.md' 是否需要像 github.com/peerigon/markdown-loader/blob/master/example/… 这样的自定义加载器? 我觉得你需要一个文件加载器,你也可以试试 md-loader。 我在没有加载器的create-react-app中使用过。 遇到此错误的人,只需在 webpack 的 raw-loader 模块中添加 .md 扩展名【参考方案5】:类似于@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 />
</>
);
【讨论】:
【参考方案6】:使用 webpack 加载器的方法
安装 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;
【讨论】:
【参考方案7】:对于 Typescript + react,请按照以下步骤操作:
-
在项目目录之一中创建一个类型定义(index.d.ts)文件,并放入以下代码。
declare module "*.md";
-
添加
tsconfig.json -> CompilerOptions -> typeRoots
如下
"compilerOptions":
...
"typeRoots": [ "<types-directory-created-in-#1>", "./node_modules/@types"],
...
-
安装两个库showdown和html-react-parser
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>
)
【讨论】:
【参考方案8】:我稍微修改了这个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;
【讨论】:
【参考方案9】:如果您使用 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'
【讨论】:
谢谢!这对我有用,我认为使用加载器比在浏览器中进行降价渲染更好。【参考方案10】:我已经尝试了上述建议,并在运行命令后推断出
> npm install markdown
import ReactMarkdown from 'markdown';
它终于对我有用了
【讨论】:
【参考方案11】:我希望它使用 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 那里得到的。我不知道它为什么有效。
【讨论】:
【参考方案12】:另一种选择是将 Markdown 放在 .js 文件中,使用反引号 ` 字符将 Markdown 作为未标记的模板文字括起来。像这样:
const MD = `
**TERMS OF SERVICE**
Last Modified: 30 November 2021...`
export default MD
然后你可以像任何其他模块一样import
它。
【讨论】:
以上是关于如何将降价文件加载到反应组件中?的主要内容,如果未能解决你的问题,请参考以下文章
如何将状态值从一个组件访问到位于单独文件中的其他功能(不是组件)?反应js