我对预期结果和实际结果有疑问。即使从数组中调用fetchData()和fetchnumberOfCommits()方法componentWillMount(),数组也没有数据。但是最后,render 方法被调用了两次,其中数组已经从 API 获取了数据。我setState()在上面提到的两个方法中都调用了该方法,其中它调用了 render 方法。我的问题是为什么在调用这两个方法后数组没有立即获取数据?以及在什么时候数组获取数据?
React.js 组件生命周期、状态行为和 JavaScript 的异步特性
IT技术
javascript
ajax
reactjs
async-await
2021-05-25 01:10:56
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>;
}
}
如上所述,您应该将其从 componentWillMount 中删除,因为它已从 16.3 开始弃用。应该能够将其放入 componentDidMount 中,它将为您工作。
我也从componentWillMount()改为 componentDidMount(),但我遇到了同样的问题。原因是 JavaScript 的异步特性。当您使用Promise时,它不会等到您从 API 调用中获得结果。它只是按照保持Promise的顺序运行代码,直到它获取数据。这就是即使调用了该函数我也得到一个空数组的原因。
您可以使用async/await 使代码同步,然后它会等待直到您从 API 调用中获得结果。如果您运行以下代码示例,您可以在控制台中看到结果,其中fetchData1()给出了一个空数组,而fetchData2()to 给出了带有数据的数组。此外,如果您仔细检查控制台,您将看到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;