【问题标题】:render method being called before API data is loaded in React在 React 中加载 API 数据之前调用 render 方法
【发布时间】:2018-10-18 20:34:13
【问题描述】:

React 的初学者。 我正在尝试在 React 中找出解决这种情况的标准方法。

我正在访问一个 api,数据返回一切正常,除了我试图将数据设置为我的组件的状态,并且 render() 方法在返回任何数据之前引用状态,因此状态属性被定义为“null”。

在下面的代码示例中,您可以看到我正在登录到控制台,尽管事情的顺序,第二个日志是在将 setState 设置为 API 数据的日志之前从浏览器返回的。

任何关于尽管使用 .then() 仍会发生这种情况的帮助/解释将不胜感激。

谢谢。

PS:为简化起见,我删除了 TeamList 组件,但与“第二个日志”一样,组件在实际拉入数据之前就已呈现。

import React, { Component } from 'react';
class App extends Component {

constructor(props) {
  super(props);
  this.state = {
    data: null,
  }
}

componentDidMount() {
  const uri = 'http://api.football-data.org/v2/competitions/PL/teams'; 

  let h = new Headers()
  h.append('Accept', 'application/json')
  h.append('X-Auth-Token', 'XXXXXXXXXXXXXXXXXXXX')
  let req = new Request(uri, {
    method: 'GET',
    headers: h,
    mode: 'cors' 
  })

  var component = this;

  fetch(req)
   .then( (response) => {
    return response.json()    
   })
   .then( (json) => {
      this.setState({ data: json })
   })
   .then( (json) => {
      console.log( 'second log', this.state.data )
   })
   .catch( (ex) => {
      console.log('parsing failed', ex)
   })
   console.log( 'first log', this.state.data )
}

render() {
  return (
    <div>
      <div className="App">
      <TeamList list={this.state.data} />
    </div>

    </div>
  );
}
}

export default App;

【问题讨论】:

  • 考虑在你的状态中添加一个加载布尔值,在你的获取链末尾设置为 false。在渲染函数中使用条件语句来加载缓冲符号或其他内容,直到加载变量设置为 false。

标签: javascript reactjs api


【解决方案1】:

当您安装一个组件时,它会立即以初始状态(您在构造函数中设置)呈现。稍后,当您调用setState 时,状态会更新并且组件会重新呈现。因此,在state.data 不为空之前显示类似“正在加载...”的内容是有意义的:

 render() {
  return (
    <div>
      <div className="App">
      {this.state.data ? <TeamList list={this.state.data} /> : "loading..." }
    </div>
    </div>
  );
 }

现在额外的日志记录不能按预期工作,因为setState 不返回承诺,所以:

    .then( (json) => {
      this.setState({ data: json })
   })
   .then( (json) => {
     console.log( 'second log', this.state.data )
   })

其实是一样的:

    .then( (json) => {
       this.setState({ data: json })
       console.log( 'second log', this.state.data )
   })

并且仍然将null 记录为setState 是异步的,这意味着调用它现在不会更改this.state,而是somewhen。要正确记录它,请使用回调:

 then( (json) => {
       this.setState({ data: json }, () => {
           console.log( 'second log', this.state.data )
       });
   })

【讨论】:

  • 谢谢你,我使用了 Nathan 的回答,你的回答很有用。
【解决方案2】:

你需要在你的 render() 开头添加这样的东西:

if (this.state.data === null) {
  return false;
}

所以你的代码应该是:

render() {
  if (this.state.data === null) {
    return false;
  }

  return (
  <div>
    <div className="App">
      <TeamList list={this.state.data} />
    </div>
  </div>
  );
}

render() 被立即调用,但你希望它返回 false,直到 this.state.data 有数据

【讨论】:

    【解决方案3】:

    只是一个想法:

    import React, { Component } from 'react';
    
    class App extends Component {
    
        constructor(props) 
        {
          super(props);
    
          this.state = {
           data: null,
          };
    
        }
    
        componentDidMount() 
        {
            fetch('http://api.football-data.org/v2/competitions/PL/teams')
            .then(response => response.json())
            .then(data => this.setState({ data }));
        }
    
        render() {
            return (
               <div>
                    <div className="App">
                        <TeamList list={this.state.data} />
                    </div>
    
               </div>
            );
        }
    }
    
    export default App;
    

    团队名单:

    class TeamList extends React.Component {
    
        constructor(props) {
            super(props);
        }
    
        render(){
    
           return (
                <ul>
                {
                    this.props.list.map((element, i) => {
                         return (
                            <li className="un-res t_d " key={i}>{element}</li>
                         )
                    }
                })
         }
    }
    
    export default TeamList
    

    编码愉快!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-02
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多