There are two ways you can solve this:
1- You are missing an await statement, but this will require for everything that is happening in their to be wrapped into an async function. Read more here
With your code, something like this should work:
useEffect(() => {
(async () => {
const selectedSdksKeys = Object.keys(selectedSdks);
await fetch(
`/api/sdk/churn?sdk1_id=${selectedSdksKeys[0]}&sdk2_id=${selectedSdksKeys[1]}&sdk3_id=${selectedSdksKeys[2]}`
)
.then((res) => res.json())
.then((res) => setAllSdksInfo(res))
// Code that must happen after:
await Promise.all (
selectedSdksKeys.map((id) => {
return fetch(`/api/sdk/app_count?sdk_id=${id}`)
.then((res) => res.json())
.then((res) => {
setAllSdksInfo(prev => ({...prev, res}))
});
});
)
})()
})
2- Alternatively, if you wish to skip that, you an just put the function you want to happen after the first in a then() statement. It should look something like this:
useEffect(() => {
const selectedSdksKeys = Object.keys(selectedSdks);
fetch(
`/api/sdk/churn?sdk1_id=${selectedSdksKeys[0]}&sdk2_id=${selectedSdksKeys[1]}&sdk3_id=${selectedSdksKeys[2]}`
)
.then((res) => res.json())
.then((res) => setAllSdksInfo(res))
.then(() => {
// Your second API call which was being run out of order:
selectedSdksKeys.forEach((id) => {
fetch(`/api/sdk/app_count?sdk_id=${id}`)
.then((res) => res.json())
.then((res) => {
setAllSdksInfo(prev => ({...prev, res}))
});
});
})
}, [selectedSdks]);
Edit: I also noticed that you are doing a forEach with a fetch inside it. This will cause the fetches to be out of order. If this is a problem, consider wrapping it in a Promise.all with a .map instead of a foreach. Something like this:
// Your second API call which was being run out of order:
return Promise.all(selectedSdksKeys.nmap((id) => {
return fetch(`/api/sdk/app_count?sdk_id=${id}`)
.then((res) => res.json())
.then((res) => {
setAllSdksInfo(prev => ({...prev, res}))
});
})
awaitbefore the firstfetchshould do the trickuseEffect(async () =>