多亏了@Filipe的回答,我得到了一些指导,并获得了一个符合您需求的工作示例。
在我的案例中,我有一个.md
文件位于assets/markdown/
文件夹中,该文件名为test-1.md
诀窍是获取文件的本地url
,然后使用fetch
API将其内容作为string
获取。
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Markdown from 'react-native-markdown-renderer';
const copy = `# h1 Heading 8-)
| Option | Description |
| ------ | ----------- |
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
`;
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
copy: copy
}
}
componentDidMount() {
this.fetchLocalFile();
}
fetchLocalFile = async () => {
let file = Expo.Asset.fromModule(require("./assets/markdown/test-1.md"))
await file.downloadAsync()
file = await fetch(file.uri)
file = await file.text()
this.setState({copy: file});
}
render() {
return (
<Markdown>{this.state.copy}</Markdown>
);
}
}
编辑:为了消除错误
无法从"App.js"解析"./assets/markdown/test-1.md"
您需要将@Filipe的片段中的packagerOpts
部分添加到您的app.json
文件中。
app.json
{
"expo": {
...
"assetBundlePatterns": [
"**/*"
],
"packagerOpts": {
"assetExts": ["md"]
},
...
}
}
编辑2:
回应@Norfeldt的评论:
虽然在我的项目中我使用react-native init
,因此对Expo并不是很熟悉,但我有一个Expo Snack,可能可以为您提供一些答案:https://snack.expo.io/Hk8Ghxoqm。
由于无法读取非JSON文件,所以它在expo snack上无法正常工作,但如果您愿意,可以在本地测试它。
使用file.downloadAsync()
将防止应用程序在该应用程序会话期间向托管您的文件的服务器发出XHR调用(只要用户不关闭并重新打开应用程序)。
如果更改文件或修改文件(模拟使用Expo.FileSystem.writeAsStringAsync()
调用),则只要组件重新呈现并重新下载文件,它就会显示更新后的内容。
每次应用程序关闭和重新打开时都会发生这种情况,因为据我所知,file.localUri
不会在每个会话中保持不变,因此您的应用程序将始终至少每次打开时调用file.downloadAsync()
。所以您应该没有问题来显示已更新的文件。
我还花了一些时间测试了使用fetch
与使用Expo.FileSystem.readAsStringAsync()
的速度,它们平均是相同的。往往情况下,Expo.FileSystem.readAsStringAsync
要快大约200毫秒,但在我看来这并不是致命问题。
我创建了三种不同的方法来获取同一个文件。
export default class MarkdownRenderer extends React.Component {
constructor(props) {
super(props)
this.state = {
copy: ""
}
}
componentDidMount() {
this.fetch()
}
fetch = () => {
if (this.state.copy) {
this.setState({copy: ""}, this.fetch)
return;
}
let asset = Expo.Asset.fromModule(md)
const id = Math.floor(Math.random() * 100) % 40;
console.log(`[${id}] Started fetching data`, asset.localUri)
let start = new Date(), end;
const save = (res) => {
this.setState({copy: res})
let end = new Date();
console.info(`[${id}] Completed fetching data in ${(end - start) / 1000} seconds`)
}
let method1 = () => {
if (!asset.localUri) {
asset.downloadAsync().then(()=>{
Expo.FileSystem.readAsStringAsync(asset.localUri).then(save)
})
} else {
Expo.FileSystem.readAsStringAsync(asset.localUri).then(save)
}
}
let method2 = () => {
if (!asset.localUri) {
asset.downloadAsync().then(()=>{
fetch(asset.localUri).then(res => res.text()).then(save)
})
} else {
fetch(asset.localUri).then(res => res.text()).then(save)
}
}
let method3 = () => {
fetch(asset.uri).then(res => res.text()).then(save)
}
method3()
}
changeText = () => {
let asset = Expo.Asset.fromModule(md)
Expo.FileSystem.writeAsStringAsync(asset.localUri, "Hello World");
}
render() {
return (
<ScrollView style={{maxHeight: "90%"}}>
<Button onPress={this.fetch} title="Refetch"/>
<Button onPress={this.changeText} title="Change Text"/>
<Markdown>{this.state.copy}</Markdown>
</ScrollView>
);
}
}
只需在这三者之间交替使用即可查看日志中的差异。