Reputation: 111
I have this function and inside forEach
loop that iterate trough items... What I want to achieve is to to render some spinner ( loader ) until all of http
requests are done, until forEach
loop is done.
The way I am trying now, first and last console.log
triggers immediately and then it logs second console.log
as many times as there are items in the items array.
How can I update state to loading: false
when forEach
iteration is done, when all http
requests are done?
someHandler = () => {
// this.setState({ loading: false })
console.log( "Not loading" )
this.props.items.forEach(item => {
axios
.get(`.../${item}/`)
.then(res => {
this.setState(prevState => ({
item: [
...prevState.item,
{
name: res.data.name,
img: res.data.img
}
]
}));
this.props.newItem(this.state.item);
// this.setState({ loading: true })
console.log( "Loading" )
})
.catch(err => {
console.log(err);
// this.setState({ loading: false })
console.log( "Not loading" )
});
});
// this.setState({ loading: false })
console.log( "Not loading" )
};
Upvotes: 1
Views: 638
Reputation: 32037
If you can't use async/await in your env, and want to wait until a number of promises are resolved, then Promise.all
is your friend. I may have missed something, but in a nutshell, you could rewrite your function to be like this:
const requests = this.props.items.map(item => (
axios.get(`...${item}`).then(res => {
const newItem = { name: res.data.name, img: res.data.img }
this.props.newItem(newItem)
return newItem
})
))
Promise.all(requests).then(responses => {
this.setState({ item: responses })
})
This creates a new array of promises called requests
and when they're all done, uses setState
to set all the responses.
Upvotes: 1
Reputation: 6289
You can use async/await
with for...of
You can assume sequential execution with this approach.
someHandler = async () => {
console.log('Not loading'); // will execute before loop
this.setState({ loading: true }); // start loading
for (let item of this.props.items) {
const res = await axios.get(`.../${item}/`);
// ... do your logic with response
console.log('Loading');
}
console.log('Not loading'); // will execute after loop
this.setState({ loading: false }); // end loading
};
Upvotes: 1