Reputation: 2079
I am developing an application in React. It has a simple search box, on submit , i am calling api1, which returns an array of data. For each of the item in the array, i need to call api2 - which should be async. Currently the code is something like this:
onSubmit() {
api1(textboxvalue).then(data => {
let currentComponent = this
if(data matches condition1) {
currentComponent.state.arrayOfElements1.push(data);
}
if(data matches condition2) {
currentComponent.state.arrayOfElements2.push(data);
}
const arrayOfElements1 = this.state.arrayOfElements1
arrayOfElements1.map(function (element) {
api2(element) -> set this.state.data1loaded
})
const arrayOfElements2 = this.state.arrayOfElements2
arrayOfElements2.map(function (element) {
api2(element) -> set this.state.data2loaded
})
}
Requirement is check data1loaded and data2loaded states in render asynchronously. But with the above code, render is called only after promise of api1 completes
Any thoughts ?
Upvotes: 0
Views: 748
Reputation: 71
@amirKovacevic is totally correct. You should NEVER mutate state directly: https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly
I don't perfectly understand your code, but I imagine you want to do something like this:
onSubmit() {
api1(textboxvalue).then(data => {
if(/* data matches condition1 */) {
this.setState(prevState => ({
arrayOfElements1: [...prevState.arrayOfElements1, data]
}), () => {
const requests1 = Promise.all(this.state.arrayOfElements1.map(function
(element) {
return api2(element)
})).then(data => this.setState({ data1loaded: true })) // I assume you want to have an indication loading was complete
})
}
})
}
Notice the callback hell I climbed myself into because I didn't use async/await. Also notice I used setState callback: https://reactjs.org/docs/react-component.html#setstate
Setting the state is asynchronous, so you shouldn't use it directly after using setState
, at least not if you want to have the new values.
Also, my example is only for the first array of elements.
Oh, and I'm new on SO, so sorry if anything is not up to usual SO comment standards. :)
Upvotes: 1
Reputation: 49
You're pushing the result to the state, instead of using setState method that would re-render component with the new state. This has nothing to do with the async nature of Promises, but rather the way React works (simplified: updating state and passing state and props to components which causes them to render).
I suggest brushing up on React basics before moving forward.
Upvotes: 1