Raf
Raf

Reputation: 245

Сollect promises results in foreach loop and only after performing setState

I am new to React and Promises.

My purpose is - Collect array of objects from several Search Services and then transfer whole array to the State.

PNP.SearchResults is a Promise

In code below this.setState is performing earlier then array is ready. How to fix it?

private getSearchResults() {
    const allSearchResults = []

    this.state.resultSources.forEach(rSource =>{
      this.props.searchService.search(this.props.AdditionalQuery, this.state.activePage, this.props.PageSize, rSource.sourceGuid).then((results: PNP.SearchResults) => {
          allSearchResults.push({Results: results, sourceGuid: rSource.sourceGuid});
          console.log("push");
      }).catch(() => {});
    })

    this.setState({PrimaryResults2: allSearchResults} as any);
    console.log("state updated");
}

Now console.log("state updated") fires earlier then console.log("push"). But I need vice versa

Upvotes: 0

Views: 630

Answers (2)

Pruthvi S
Pruthvi S

Reputation: 21

If i understand correctly, you need to first push the search results into allSearchResults array and then setState. Why not use async await and a basic for loop instead of .then. When you use .then, only the code in the .then callback will execute after the promise is resolved but the other code outside it like this.setState, console.log won't wait till you push all the search results.

async func() {
   const allSearchResults = [];
   for(let i=0; i<this.state.resultSources.length; i+=1){
      const item = await this.props.searchService.search(this.props.AdditionalQuery, this.state.activePage, this.props.PageSize, this.state.resultSources[i].sourceGuid)
      allSearchResults.push({Results: item, sourceGuid: this.state.resultSources[i].sourceGuid})
   }

  this.setState({PrimaryResults2: allSearchResults} as any, () => {console.log("state updated")})
}

Upvotes: 1

Viet Dinh
Viet Dinh

Reputation: 1961

Because of this.props.searchService.search is async function.

You should await result to make sure data return.

private async getSearchResults() {
    const allSearchResults = []

    for (const rSource of this.state.resultSources) {
        await this.props.searchService.search(this.props.AdditionalQuery, this.state.activePage, this.props.PageSize, rSource.sourceGuid).then((results: PNP.SearchResults) => {
            allSearchResults.push({Results: results, sourceGuid: rSource.sourceGuid});
            console.log("push");
        }).catch(() => {});
    }

    this.setState({PrimaryResults2: allSearchResults} as any);
    console.log("state updated");
}

Upvotes: 1

Related Questions