How do I stop a component rendering before data is fetched?
Control your async actions using then
or await
and use this.state
to control whether or not your content gets loaded. Only render your content after this.state.loaded === true
constructor(props) {
super(props)
this.state = {
loaded: false
}
}
async componentDidMount() {
await this.props.getTotalHours()
await this.props.getTrained()
this.setState({loaded: true})
}
content() {
let hours = parseInt(_.map(this.props.hours, 'hours'));
let trained = _.map(this.props.trained, 'trained');
return (
<div className="o-layout--center u-margin-top-large">
<div className="o-layout__item u-width-1/2@medium u-width-1/4@large">
<div style={{width: '80%', margin: '0 auto'}}>
<PieChart data={hours} goal={100} label=' Training Hours Completed'/>
</div>
</div>
)
}
render() {
return (
<div>
{this.state.loaded ? this.content() : null}
</div>
)
}
edit: If you care about performance in your API calls, you can run them in parallel with Promise.all
.
async componentDidMount() {
const hours = this.props.getTotalHours()
const trained = this.props.getTrained()
await Promise.all([hours, trained])
this.setState({loaded: true})
}
In your constructor, declare a state variable to track if data is loaded. For example:
constructor (props) {
super(props)
this.state = {
dataLoaded: false
}
}
Then in your render
method, return null if this.state.dataLoaded
is false:
render () {
const { dataLoaded } = this.state
return (
<div>
{
dataLoaded &&
<YourComponent />
}
</div>
)
}
And in the methods you use to fetch data, make sure you call this.setState({ dataLoaded: true })
when data has been fetched