How do I stop a component rendering before data is fetched?

前端 未结 3 1996
后悔当初
后悔当初 2021-02-04 17:03

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, dependin

相关标签:
3条回答
  • 2021-02-04 17:50

    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})
     }
    
    0 讨论(0)
  • 2021-02-04 17:51

    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

    0 讨论(0)
  • 2021-02-04 17:55

    You can't stop the render but you can give conditions to what to render.

    Example

    render() {
        if(this.props.hours. length <= 0 || this.props.trained.length <= 0 ) {
          return (<div><span>Loading...</span></div>);
        } else {
          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>
          )
        }
    
    0 讨论(0)
提交回复
热议问题