I am trying to get a combined result from multiple promises inside a React hook.
But when I use the hook, the function getAll
immediately returns empty, instead of returning all MyType
s.
My Hook: (api.get
returns a Promise<MyType[]>
)
function useMyHook() {
const api = useApiService();
return {
getAll,
};
function getAll(arr: number[]): MyType[] {
const results: MyType[] = [];
for (const u of arr) {
api.get(u).then((res) => {
results.push(...res);
});
}
return [...new Set(results)];
}
}
Usage:
function MyComponent() {
// ...
const myHook= useMyHook();
const use = () => {
// ...
const numbers = [1, 2, 3];
const myTypes = myHook.getAll(numbers);
const count = myTypes.length; // this will always be 0
// ...
};
}
How can I make this work? I have tried multiple versions with promise chaining and async/await, but to no avail.
Since api.get
returns a promise, getAll
will need to return a promise too. It can't return a MyType[]
, since it takes time to assemble that array. I would use Promise.all to create a new promise that will wait for the individual promises, and then have some code after to combine the results.
With async/await:
function async getAll(arr: number[]): Promise<MyType[]> {
const promises: Promise<MyType[]>[] = [];
for (const u of arr) {
promises.push(api.get(u));
}
const results = await Promise.all(promises);
// results is an array of arrays, so we need to flatten it
return [...new Set(results.flat())];
}
// used like:
const use = async () => {
// ...
const numbers = [1, 2, 3];
const myTypes = await myHook.getAll(numbers);
const count = myTypes.length;
// ...
};
Or if you prefer using .then
:
function getAll(arr: number[]): Promise<MyType[]> {
const promises: Promise<MyType[]>[] = [];
for (const u of arr) {
promises.push(api.get(u));
}
return Promise.all(promises).then(results => {
// results is an array of arrays, so we need to flatten it
return [...new Set(results.flat())];
});
}
// used like:
const use = () => {
// ...
const numbers = [1, 2, 3];
myHook.getAll(numbers).then(myTypes => {
const count = myTypes.length;
// ...
});
};