Javascript render()方法不是';当状态改变时不总是调用?(反应中的怪异行为)

Javascript render()方法不是';当状态改变时不总是调用?(反应中的怪异行为),javascript,reactjs,api,asynchronous,fetch,Javascript,Reactjs,Api,Asynchronous,Fetch,我正在学习react,并尝试使用足球数据API对前5名联赛的足球排名进行编码,但有一个奇怪的问题。 我了解到,每次更改状态时,都会调用render()。在我的代码中,从API获取数据后不会调用render()。 方法getAllStandings()在开始时被调用,对于CompetitionSID数组的每个competitionId,它都会获取该站。迭代每个id之后,状态将更新,并且应该调用render()方法,但它不会。render()方法中的变量为空。 可能是因为异步函数 下面是我的代码(在

我正在学习react,并尝试使用足球数据API对前5名联赛的足球排名进行编码,但有一个奇怪的问题。 我了解到,每次更改状态时,都会调用render()。在我的代码中,从API获取数据后不会调用render()。 方法getAllStandings()在开始时被调用,对于
CompetitionSID
数组的每个
competitionId
,它都会获取该站。迭代每个id之后,状态将更新,并且应该调用render()方法,但它不会。render()方法中的变量为空。 可能是因为异步函数

下面是我的代码(在componentDidMount()方法中调用getAllStandings()):

getAllStandings(){
让列表=[];
让竞赛=this.state.competitionsIds;//[1,2,3,4,5]
控制台日志(“竞赛:”,竞赛);
竞赛。forEach((项目,i)=>{
this.getStandingById(item).then((数据)=>list.push(数据));
});
这是我的国家({
排行榜
},()=>console.log(“standingsList:,this.state.standingsList));
}
异步getStandingById(competitionId){
//console.log(“获取id为、competitionId为的竞赛站名”);
const url=this.state.url.concat(“competitions/”).concat(competitionId).concat(“/standings/”);
常量选项={
方法:“GET”,
标题:{
“X-Auth-Token”:this.state.Auth
}
};
let response=等待获取(url、选项);
让data=wait response.json();
返回等待数据;
}
render(){
让standingsArr=this.state.standingsList;
log(“standingsArr:”,JSON.stringify(standingsArr));
console.log(“长度:”,standingsharr.length);
返回(
{this.state.standingsList.map((项)=>(
))}
);
}

您没有正确处理异步操作

let list=[];
控制台日志(“竞赛:”,竞赛);
竞赛。forEach((项目,i)=>{
this.getStandingById(item).then((数据)=>list.push(数据));
});
这是我的国家({
排行榜
},()=>console.log(“standingsList:,this.state.standingsList));
forEach
将在对
getStandingById
的所有调用完成之前完成,因此您的
列表将不会包含所需的所有数据。在调用
setState
之前,需要等待所有这些调用完成。将它们全部收集到一个数组中并使用可以实现以下目的:

let list=[];
控制台日志(“竞赛:”,竞赛);
常量承诺=[];
竞赛。forEach((项目)=>{
const promise=this.getStandingById(项)。然后((数据)=>list.push(数据));
承诺。推动(承诺);
});
承诺。所有(承诺)。然后(()=>{
这是我的国家({
排行榜
});
});
请注意,数据推送到
列表的顺序并非每次都相同。如果顺序很重要,那么不要使用forEach
,因为它们将同时启动。相反,您可以使用一个正常的
循环,并
等待
每次调用
getStandingById
,然后继续进行下一场比赛,如下所示:

异步getAllStandings(){ 让列表=[]; 控制台日志(“竞赛:”,竞赛); 用于(竞赛的常数项){ //按顺序操作以保持秩序 等待这个。getStandingById(item)。然后((数据)=>list.push(数据)); }); 这是我的国家({ 排行榜 }); }
您的getStandingById函数有问题,您的forEach将在调用setState之前结束,因此您需要等待承诺的结果,您可以使用封装在承诺中的映射来完成。注意,我将getAllStandings更改为异步函数

async getAllStandings(){
    let competitions = this.state.competitionsIds; // [1,2,3,4,5]
    console.log("Competitions: ", competitions);
    const list = await Promise.all(competitions.map((item, i) => {
      return this.getStandingById(item);
    }));

    this.setState({
      standingsList: list
    },() => console.log("standingsList: ", this.state.standingsList));
  }
async getAllStandings(){
    let competitions = this.state.competitionsIds; // [1,2,3,4,5]
    console.log("Competitions: ", competitions);
    const list = await Promise.all(competitions.map((item, i) => {
      return this.getStandingById(item);
    }));

    this.setState({
      standingsList: list
    },() => console.log("standingsList: ", this.state.standingsList));
  }