我在componentDidMount内嵌套了两个api调用,一切正常,唯一的问题是状态未更新,因此我放置了一些控制台日志以查看发生了什么
fetch reviews done! analysis done! false analysis done! false analysis done! false
如您所见,loaded永不更新的状态以及应用程序上没有数据显示的状态,我可能使用此功能弄乱了逻辑,但我无法弄清楚。
loaded
componentDidMount = () => { this.setState({ loading: true }); fetch( "https://url-one.com", { headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "X-Spree-Token": "xxx" } } ) .then(response => response.json()) .then(responseJson => { console.log('fetch reviews done!') this.setState( { list: responseJson.reviews, }, () => { var obj = this.state.list; var data = []; for (let i in obj) { fetch( "https://url-two.com", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ api_key: "uuu", data: obj[i].text }) } ) .then(response => response.json()) .then(responseJson => { data.push({'review': obj[i].text, 'analysis': responseJson.results * 100}); }); this.setState({ data: data, loaded: true, loading: false, }); console.log('analysis done!') console.log(this.state.loaded) } } ); }); }
当然,如果我使用一个单独的函数来更新状态,那么它将起作用!
show = () => { this.setState({ loaded: true }); };
如您所见,加载状态永远不会更新
因为setState异步发生(不是立即更新),所以使用console.log(this.state.loaded)like不能按预期工作,相反,您可以像setState第二个fetch一样使用回调,如下所示:
setState
console.log(this.state.loaded)
fetch
this.setState( { data: data, loaded: true, loading: false }, () => { console.log('analysis done!'); console.log(this.state.loaded); } );
我认为我们应该使用Promise.all()使其工作,如下所示:
componentDidMount() { this.setState({ loading: true }); fetch('https://url-one.com', { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'X-Spree-Token': 'xxx' } }) .then(response => response.json()) .then(responseJson => { console.log('fetch reviews done!'); this.setState( { list: responseJson.reviews }, () => { var obj = this.state.list; var data = []; var fetchArr = []; for (let i in obj) { let promise = fetch('https://url-two.com', { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ api_key: 'uuu', data: obj[i].text }) }).then(response => response.json()); fetchArr.push(promise); // make an array of promises } Promise.all(fetchArr).then(values => { //after all promises resolved, we'll receive an array of responseJson, we'll loop through it values.forEach((responseJson, i) => { //for each responseJson, we push it to the data array data.push({ review: obj[i].text, analysis: responseJson.results * 100 }); }); // finally, we update state this.setState( { data: data, loaded: true, loading: false }, () => { console.log('analysis done!'); console.log(this.state.loaded); } ); }); } ); }); }