如何使用React延迟加载远程数据

时间:2019-10-20 06:28:14

标签: javascript reactjs fetch

我对React还是很陌生,我正试图延迟加载存储在服务器上的markdown文件。

我尝试设置一个异步箭头功能来获取文件并通过标记运行它。 我在https://codesandbox.io/s/7zx3jlrry1处找到了这个演示,我尝试了它,但还没有弄清楚如何遵循它。

class Markdown extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            // some state
        }
    }

    render() {
        let markdown = React.lazy(async () => {
            // fetch the file
            const response = await fetch(path)
            if (!response.ok) {
                return (<p>Response was not ok</p>)
            } else {
                // if successful, return markdown
                let blob = await response.blob()
                return marked(blob)
            }
        })
        return  (
            <React.Suspense fallback={<div class="markdown">Loading</div>}>
                <div class="markdown" id={this.props.id} dangerouslySetInnerHTML={{__html: markdown}} />
            </React.Suspense>
        )
    }
}

当我尝试调试它时,箭头函数实际上并未执行,并且div的内部HTML是“ [object Object]”。 对于我如何实现这一目标的任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:1)

您在HTML中得到[object Object],因为dangerouslySetInnerHTML需要一个返回对象{__html: '<div>some html string</div>'}的函数。除此之外,您没有使用建议的通过网络请求获取数据的方式。请继续阅读以获取有关如何执行任务的更多详细信息。

React Suspense用于延迟加载Components,而不是像react docs所声明的那样获取数据:

  

将来,我们计划让Suspense处理更多方案,例如数据提取

     

React.Suspense可让您指定加载指示器,以防其下方树中的某些组件尚未准备好呈现。如今,延迟加载组件是唯一受支持的用例

在这种情况下,您不需要延迟加载。使用react-lifecycle方法来执行诸如在正确时间获取数据之类的事情。您在这里需要的是react-lifecylce方法componentDidMount。您也可以使用component state来控制呈现的内容和未呈现的内容。例如,您可以通过设置变量来显示error occuredloading

class Markdown extends React.Component {
	constructor(props) {
		super(props)
		this.state = {
			loading: true,
			error: false,
			html: ""
		}
	}

	componentDidMount = () => {
		this.fetchMarkdown()
	}

	fetchMarkdown = async () => {
		const response = await fetch(path)
		if (!response.ok) {
			// if failed set loading to false and error to true
			this.setState({ loading: false, error: true })
		} else {
			// If successful set the state html = markdown from response
			let blob = await response.text()
			this.setState({ loading: false, html: blob })
		}
	}

	getMarkup = () => {
		return { __html: this.state.html }
	}

	render() {
		if (this.state.error) {
			return <div>Error loading markup...</div>
		}
		else if (this.state.loading){
			return <div>Loading...</div>
		} 
		else {
			return <div class="markdown" id={this.props.id} dangerouslySetInnerHTML={this.getMarkup()} />
		}
	}
}