javascript 如何在获取数据之前停止组件渲染?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46825735/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:57:29  来源:igfitidea点击:

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

javascriptreactjsreduxreact-redux

提问by Matt Ellis

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 生命周期方法中调用操作创建者来获取数据。然而,该组件使用数据,这取决于响应的速度确定数据是否存在。我如何才能使组件在数据在其中之前不呈现?

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:

Action Creator 将请求的返回值存储在应用程序状态:

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

回答by Andrew

Control your async actions using thenor awaitand use this.stateto control whether or not your content gets loaded. Only render your content after this.state.loaded === true

使用then或控制您的异步操作,await并使用this.state控制您的内容是否被加载。仅在之后呈现您的内容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.

编辑:如果您关心 API 调用的性能,则可以与Promise.all.

async componentDidMount() {
   const hours = this.props.getTotalHours()
   const trained = this.props.getTrained()
   await Promise.all([hours, trained])
   this.setState({loaded: true})
 }

回答by 3Dos

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 rendermethod, return null if this.state.dataLoadedis false:

然后在您的render方法中,如果this.state.dataLoaded为 false ,则返回 null :

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

在你用来获取数据的方法中,确保你在获取数据this.setState({ dataLoaded: true })时调用

回答by bennygenel

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