Reputation: 363
I have a few functions which return Promise responses. I am now trying to grab all of them and send all the data to the backend. However, I don't know how to grab them all. I have it like:
componentDidMount() {
Promise.all([
this.getFunction1Data(ONEDAYINTERVAL), //returns an array of objects
this.getFunction2Data(ONEDAYINTERVAL),
this.getFunction3Data(ONEDAYINTERVAL),
]).then(([response1, response2, response3]) => {
this.sendDataToServer(response3);
// do stuff with your data
}).catch(e => console.error);
}
But the issue here is, that somehow they're all mixed.
Example: sometimes reponse2 has data from all three functions, and sometimes response3 has all the data needed, while response2 is missing a few objects. How would I fix that? Should there be some function to form an array from all of the responses(with a check if element exists) or there is a way around? Just for the double-check I am adding an example of a function here (others are identical):
getFunction1Data(dateFrom) {
return new Promise((resolve) => {
AppleKit.initKit(KitPermissions.uploadBasicKitData(), (err, results) => {
if (err) {
return;
}
AppleKit.getSamples(dateFrom, (err, results) => {
if (err) {
return resolve([]);
}
const newData = results.map(item => {
return { ...item, name: "Item1" };
});
const allData = [...this.state.ActivityItem, ...newData];
this.setState({ ActivityItem: allData });
resolve(allData);
});
})
})
}
UPDATE Second Function:
getFucntion2Data(dateFrom) {
return new Promise((resolve) => {
AppleKit.initKit(KitPermissions.uploadBasicKitData(), (err, results) => {
if (err) {
return;
}
AppleHealthKit.getStepsSample(datefrom, (err, results) => {
if (err) {
return resolve([]);
}
const newData = results.map(item => {
return { ...item, name: "StepsSample" };
});
this.setState(({ActivityItem}) => {
ActivityItem = [...ActivityItem, ...newData];
resolve(ActivityItem);
return { newData }
});
});
})
})
}
Upvotes: 1
Views: 594
Reputation: 1074335
The major problem is here in getFunction1Data
:
const allData = [...this.state.ActivityItem, ...newData];
this.setState({ ActivityItem: allData });
You're setting state based on existing state. Whenever you do that, you need to use the callback form of setState
, not the form you pass state to directly. The reason is that state updates may be asynchronous and are "batched" when you make several changes between renders. So this.state.ActivityItem
can be out of date when you build the new state you're giving to setState
.
To use the callback form, don't have allData
at all, and do:
this.setState(({ActivityItem}) => {
ActivityItem = [...ActivityItem, ...newData];
resolve(ActivityItem);
return { ActivityItem }
});
The separate problem is that you have each call to getFunction1Data
returning (via the promise) all of the gathered data, not just the data gathered by that call. It's not entirely clear to me what you want to do, but I'd lean toward having getFunction1Data
return only the data it gathered (newData
), not all the data, or to modify it so that it gets all of the information you want to get, not just one third of it, so you can call it just once.
Upvotes: 2