Replies: 3 comments 6 replies
-
One component for each would render all at once and create all of the promises at the same time, so you would likely still be loading in parallel. For sequential loading (or just sequential promises in general), you can do something like: const useValues = (ids) => {
return useQuery(['queryKey', { ids }], async (key, { ids }) => {
const result = []
for (const id in ids) {
const value = await api.getValue(id)
console.log('***** loaded:', value)
result.push(value)
}
return result
})
} An imperative loop like |
Beta Was this translation helpful? Give feedback.
-
Note that the above waits to return the array until all are finished. If you want to render each as it finishes, another solution that's pretty slick would be using the p-limit library. It throttles requests internally, so as long as all instances of your hook share the same "limit lock", each will be blocked until another finishes. This has the added benefit of allowing a configurable number. I.e. maybe loading 50 all at once causes issues, but it's it ok to do a smaller number concurrently. import pLimit from 'p-limit'
// declare outside of the hook, so all instances use the same one
// can change the 1 to however many can safely run at the same time
const limit = pLimit(1)
const useValue = (id) => {
return useQuery(['valueKey', { id }], async (key, { id }) => {
return limit(() => api.getValue(id))
})
} |
Beta Was this translation helpful? Give feedback.
-
A couple of months ago I forked the V1 branch of react-query and developed a useQueries hook like this: const [{data: data1}, {data: data2}, {data: data3}] = useQueries(
[keyAndParams1, keyAndParams2, keyAndParams3],
fetchFn,
opts,
); It’s based on another hook which I called const results = inputs.map(someHook) But nothing stops us from doing this: const results = someHook(inputs) And that’s the idea behind useManyEffects - to work with collections. The changes to react-query were mostly about adding one extra file for that new hook. I was able to reuse the existing under-the-hood mechanisms to make it work. It’s been working great and it’s not causing any problems. It allows to cache individual items and deduplicate requests. All without the need of altering the components tree or implementing inter-component communication. Looking at it now, if I were to redo it, I think I’d go one step further and shape the API like this: const [{data: data1}, {data: data2}, {data: data3}] = useQueries(
[[key1, param1, param2, fetchFn1, opts1], [key2, param3, fetchFn1], [key, fetchFn2, opts2]],
); I’ve had no need of anything like this yet, but I like the simplicity that comes with making every parameter a member of a collection. What do you think about it? Would that help you to build your apps? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
The issue I have is that if I use a
Promise.all
inside of the async function ofuseQuery
, all of the API calls are called together, when I would really like to cache each call separately and make sure that only one call is made at a time for each, as the response payloads are very large.For example:
fetch
.4
. The app should start loading the data for the 4th item, without cancelling the queries for the previous 3 items.A few notes:
usePaginatedQuery
, since it seems like it only returns one "page" at a timeuseInfiniteQuery
, since I need to fetch multiple "sections" at a time, and I cannot remove a query from the results unless I track it externallyuseQuery
because I need to do aggregations on the completed dataset.useQuery
, using some sort of clever state or cache handling, which is what I think I will do for now, but it seems a little hacky and a lot of manual effortMaybe a hook like this will benefit the library? (where data is an array of results corresponding to the items in
queries
)Or maybe something like this makes more sense:
Or... maybe there's a way to do all this already with the library, if anyone cares to share their solution?
Editing to answer my own question: I guess the easiest way to do this with the current API would be to mount one component for each query, and in the parent, use
queryCache
to subscribe to each query key and respond to data changes. This actually feels pretty straightforward to me.Beta Was this translation helpful? Give feedback.
All reactions