Reputation: 75
I'm fairly new to React and I'm trying to lazy load a markdown file stored on the server.
I've tried setting up an async arrow function that fetches the file and runs it through marked. I found this demo here https://codesandbox.io/s/7zx3jlrry1 which I've tried following but haven't figured out how to follow it.
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>
)
}
}
When I try debugging it the arrow function isn't actually executed, and the inner HTML of the div is "[object Object]". Any help as to how I can achieve this would be greatly appreciated.
Upvotes: 0
Views: 1633
Reputation: 896
You get [object Object]
in your html because dangerouslySetInnerHTML expects a function returning the object {__html: '<div>some html string</div>'}
. Other than that you are not using recommended way of fetching data through network requests. Please read on to get more details on how to perform your task.
React Suspense is used to lazy load Components
not for fetching data as the react docs state:
In the future we plan to let Suspense handle more scenarios such as data fetching.
React.Suspense lets you specify the loading indicator in case some components in the tree below it are not yet ready to render. Today, lazy loading components is the only use case supported by :
You don't require lazyload in this scenario. Use react-lifecycle methods in order to do things like fetching data at the correct time. What you require here is react-lifecylce method componentDidMount
. Also you can use component state
to manipulate what is rendered and what is not. e.g you can show error occured
or loading
by setting variables.
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()} />
}
}
}
Upvotes: 1