【问题标题】:React.js component life cycle, state behavior and asynchronous nature of JavaScriptReact.js 组件生命周期、状态行为和 JavaScript 的异步特性
【发布时间】:2019-03-26 02:20:02
【问题描述】:

我对预期结果和实际结果有疑问。即使从componentWillMount() 调用了fetchData()fetchnumberOfCommits() 方法,数组仍然没有数据。但最后,render 方法被调用了两次,数组已经从 API 中获取了数据。 我在上面提到的两个调用render方法的方法中都调用了setState()方法。 我的问题是为什么数组没有在调用这两种方法时立即获取数据?数组在什么时候获取数据?

Code example

【问题讨论】:

  • 您不应该在 componentWillMount 上获取数据,但如果您决定这样做,请将 componentWillMount 设为异步函数。您应该在 componentDidMount 上调用 fetchnumberOfCommits
  • 感谢您的评论我得到了答案。以下链接显示了如何制作 componentWillMount 和 asyn 功能。 (valentinog.com/blog/how-async-await-in-react)

标签: javascript ajax reactjs async-await


【解决方案1】:

我也从componentWillMount() 更改为componentDidMount(),但我遇到了同样的问题。原因是 JavaScript 的异步特性。当您使用 Promise 时,它​​不会等到您从 API 调用中获得结果。它只是按照承诺的顺序运行代码,直到它获取数据。这就是即使调用了函数,我也得到了一个空数组的原因。

您可以使用async/await 使代码同步,然后它会等到您从 API 调用中获得结果。 如果您运行以下代码示例,您可以在控制台中看到结果,其中fetchData1() 给出了一个空数组,fetchData2() 给出了带有数据的数组。此外,如果您仔细检查控制台,您将看到当@ 987654326@函数被调用render()方法触发。

import React, { Component } from 'react';

class App extends Component {
  constructor(){
    console.log('This is from constructor');
    super();     
    this.state={
      repositories:[],
  }  
  }
  componentDidMount(){
    console.log('This is from componentDidMount');
    this.fetchData1();
    this.fetchData2();
  }
  fetchData1(){
        console.log('This is function is using promises');
        fetch('https://api.github.com/users/94ju/repos').then(results => results.json()).then(repositories =>this.setState({ 
          repositories
        })).then( 
          console.log( this.state.repositories),
          console.log(this.state)
        ) 
        console.log('End of using promises')

  }
  async fetchData2(){
    console.log('This is function is using async-await');
    const check =await fetch('https://api.github.com/users/94ju/repos');
    const checkjson =await check.json();
    console.log('Before setState');
    this.setState({ async_repositories: checkjson });
    console.log( this.state.async_repositories);
    console.log(this.state);
    console.log('End of async-await');
}
  render() {
    console.log("Starting render function");
    const repo =this.state;
    console.log(repo);
    console.log('Ending render function');
    return (
      <div>

      </div>
    );

  }
}

export default App;

【讨论】:

    【解决方案2】:

    如上所述,您应该将其从 componentWillMount 中删除,因为它已在 16.3 中被弃用。应该能够将其放入 componentDidMount 中,它会为您工作。

    【讨论】:

      【解决方案3】:

      render 方法在组件第一次挂载时被调用,并且在你的数据被接收并且状态发生改变时再次被调用。这就是为什么您会看到 render 方法被调用了两次。

      componentWillMount() 在 React 16.3 中被弃用。您应该使用componentDidMount() 来获取数据,并且您应该期望您的组件在获取数据之前至少呈现一次,因此您需要在获取数据之前呈现null 或加载状态。我提供了一个示例,说明如何检查它是否正确加载并显示加载消息。

      class App extends React.Component {
      
        constructor() {
          super();
          this.state = {
            check: true,
            repositories: [],
            commits: [],
          };
        }
      
        componentDidMount() {
          this.fetchData();
          this.fetchNumberOfCommits();
        }
      
        fetchData() { /*...*/ }
        fetchNumberOfCommits() { /*...*/ }
      
        isLoaded() {
          return this.state.respositories.length > 0;
        }
      
        render() {
          const { repositories } = this.state;
      
          if(isLoaded) {
            return repositories.map(repo => {
              return (
                <Api
                  repo={repo.name}
                  createdDay={repo.createdDay} 
                />
              );
            });
          }
      
          return <h1>Loading repos...</h1>;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-10
        • 1970-01-01
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多