渲染中的React状态在return内部不可用

时间:2018-12-06 19:52:15

标签: javascript reactjs state

我有这些方法来进行某些提取,然后完成设置状态。但是渲染是在状态完成之前调用的,并且不会更新。

以下内容似乎可以自行解决,但需要一分钟才能完成。

     //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。我该怎么办?

添加小提琴:https://jsfiddle.net/drumgod/e2atysu3/6/

2 个答案:

答案 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通话。