我对预期结果和实际结果有疑问。即使从fetchData()
调用了fetchnumberOfCommits()
和componentWillMount()
方法,该数组也没有数据。但最后,render方法被调用了两次,其中数组已从API获取数据。
我在上述两个方法中都调用setState()
方法,其中它调用了render方法。
我的问题是,为什么在调用这两个方法后数组不立即获取数据?数组在什么时候获取数据?
答案 0 :(得分:2)
在第一次安装组件时调用render方法,并且在接收到数据并且状态已更改时再次调用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>;
}
}
答案 1 :(得分:0)
如上所述,您应该将其从componentWillMount中删除,因为从16.3开始不推荐使用。应该能够将其放入componentDidMount中,它将为您工作。
答案 2 :(得分:0)
我也从componentWillMount()
更改为componentDidMount()
,但遇到了同样的问题。原因是JavaScript的异步特性。当您使用诺言时,它不会等到您从API调用中获得结果。它只是将代码按顺序运行,并保持承诺获取数据。这就是即使调用该函数也得到一个空数组的原因。
您可以使用async/await
使代码同步,然后它将等待直到您从API调用中获得结果。
如果运行以下代码示例,您将在控制台中看到结果,其中fetchData1()
给出了一个空数组,而fetchData2()
给出了包含数据的数组。如果您仔细检查一下控制台,您将看到当调用setState()
函数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;