我有这些方法来进行某些提取,然后完成设置状态。但是渲染是在状态完成之前调用的,并且不会更新。
以下内容似乎可以自行解决,但需要一分钟才能完成。
//returns an promise with Array
getTopIDs(url) {
return fetch(url).then(blob => blob.json()).then(json => json)
}
// makes a URL fetchs JSON and return promise with single ID
getStory(id) {
let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`
return fetch(url).then(blob => blob.json()).then(json => json)
}
// call above methods, set state when done
componentDidMount() { //
let arr = []
let promise = new Promise((resolve, reject) => {
let data = this.getTopIDs("https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty").then((idArr) => {
idArr.forEach((id, index) => {
this.getStory(id).then(res => {
arr.push(res)
})
})
//resolve once all pushed to arr
resolve(arr)
})
})
// set state once array is completed
promise.then(res => {
return this.setState({data: arr})
})
}
然后在其下方的渲染器中记录“否”,“否”并停止。在返回值之外尝试它会记录“否”,“是”。在搜索其他帖子时,我尝试在完成后设置布尔值并使用状态回调,但这些无效(完全披露:我不太了解setState回调选项)
render() {
return (
<div>
{
this.state.data.length
? console.log('yes')
: console.log('no')
}
</div>)
}
仅在完成后,我才需要渲染来处理this.state.data
。我该怎么办?
答案 0 :(得分:0)
您的方法this.getStory()
是异步的,但是您对数组创建的处理在您的promise中是同步的。
您需要使用async/await
或仅在确定完成resolve(arr)
之后运行idArr.forEach()
(使用Promise.all(idArr.map(...))
可能更容易,其中{{1 }}从...
返回结果。
答案 1 :(得分:0)
这是您要在getStory
中设置状态的方法:
this.setState(prevState => ({
data: [...prevState.data, res]
}))
如评论中所述,这将为forEach
中的每个数据点呈现组件。
为避免此问题,这是componentDidMount()
的格式:
componentDidMount() {
const arr = [];
this.getTopIDs("https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty").then((idArr) => {
idArr.forEach((id, index) => this.getStory(id).then(res => arr.push(res)));
this.setState(prevState => ({ data: [...prevState.data, arr] }))
})
}
这也使您摆脱了最后的promise.then
通话。