Tuesday, June 4, 2024
 Popular · Latest · Hot · Upcoming
10
rated 0 times [  16] [ 6]  / answers: 1 / hits: 18325  / 7 Years ago, thu, october 19, 2017, 12:00:00

Currently in react I have to functions in the componentDidMount lifecycle method in which call action creators to which fetch data. The component uses the data however, depending on how quick the response is determines if the data is there or not. How can i make it so the component doesn't render before data is inside it?



componentDidMount() {
this.props.getTotalHours()
this.props.getTrained()
}


Render Function:



render() {
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>


Action Creator stores returned values from request in the application state:



 export function getTotalHours() {
const url = `${ROOT_URL}dashboard/hours`
const request = axios.get(url)
return {
type: FETCH_HOURS,
payload: request
}
}

More From » reactjs

 Answers
48

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})
}

[#56184] Monday, October 16, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
daijac

Total Points: 568
Total Questions: 120
Total Answers: 108

Location: Virgin Islands (U.S.)
Member since Fri, May 7, 2021
3 Years ago
;