Reputation: 3006
The closest answer I could find was this, which didn't help since I need to setState: How do I run a function after using array.map?
I think the answer should be simple, but I'm pretty new to Javascript. I'm trying to move the setState for isLoading
to AFTER I've pulled all of the profiles.
componentDidMount() {
console.log('MatchesScreen init props: ', Object.keys(this.props))
Object.keys(this.props.profile.profile.matches).map((username) => {
console.log('match', username)
url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username
fetch(url, {
method: 'GET',
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
})
this.props.addMatch(responseJson)
})
.catch((error) =>{
console.error(error);
})
})
}
I've tried various things like appending a .then()
to the map function, but so far no luck.
Upvotes: 1
Views: 1266
Reputation: 950
Try wrapping the Object.keys()
in a while loop with an if statement at the end.
var profilesMatched = 0;
while(profilesMatched < Object.keys(this.props.profile.profile.matches).length){
Object.keys(this.props.profile.profile.matches).map((username) => {
console.log('match', username)
url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username
fetch(url, { method: 'GET', })
.then((response) => {response.json()})
.then((responseJson) => {
this.props.addMatch(responseJson);
profilesMatched++;
})
.catch((error) => {
console.error(error);
});
});
if(profilesMatched == Object.keys(this.props.profile.profile.matches).length){
this.setState({
isLoading: false,
})
}
}
Upvotes: 0
Reputation: 556
You could return each promise inside the .map()
function, which would leave you with an array of promises. Once you have that, you can use Promise.all()
to wait for all the promises in the array to resolve.
componentDidMount() {
console.log('MatchesScreen init props: ', Object.keys(this.props))
// Put all promises into an array
const promisesArray = Object.keys(this.props.profile.profile.matches).map((username) => {
console.log('match', username)
url = 'https://xxxxxxx.execute-api.us-west-2.amazonaws.com/prod/profile?username=' + username;
// Return each promise
return fetch(url, {
method: 'GET',
})
.then((response) => response.json())
.then((responseJson) => {
this.props.addMatch(responseJson)
})
.catch((error) =>{
console.error(error);
});
});
// Wait for all promises in array to resolve
Promise.all(promisesArray)
.then(() => {
// This will execute once all promises have resolved
this.setState({
isLoading: false,
});
})
.catch(e => console.error(e));
}
Upvotes: 3
Reputation: 5508
Try using the async
/await
pattern as follows:
async componentDidMount() {
...
Object.keys(this.props.profile.profile.matches).map((username) => {
...
await fetch(url, {
...
then move your setState
method into its own callback, which you can call in your .then()
statements following your fetch
.
I like this reference: https://alligator.io/js/async-functions/
Upvotes: 0