在React中加载API数据之前调用render方法

时间:2018-10-18 20:34:14

标签: javascript reactjs api

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;

3 个答案:

答案 0 :(得分:2)

安装组件时,它会立即以初始状态(您在构造函数中设置的状态)呈现。然后,稍后,当您调用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而是何时。要正确记录它,请使用回调:

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

答案 1 :(得分:1)

您需要在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有数据为止

答案 2 :(得分:0)

一个想法:

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;

TeamList:

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

编码愉快!