Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch n dependent data with react-query

I need help with react-query library. I fetch a list of objects and then for everyone I need to fetch additional data from another service. How should I do this with react-query useQuery hook?

Example 1:

const { data} = useQuery("USERS", fetchUsers);
data.map(user => useQuery(["ACCOUNT", {userId: user.id}], 
                 ({userId}) => fetchAccount(userId)));

Error:

ESLint: React Hook useQuery cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function. (react-hooks/rules-of-hooks)

like image 973
Michał Mielec Avatar asked Feb 17 '20 10:02

Michał Mielec


1 Answers

I found the anwser provided by the author of react-query:

From what you've described, this appears to be the classic "I want to use React hooks in array-mode", which we've definitely all been in before.

99.9% of the time, I feel the answer to this predicament is to render hook usages into multiple components and compose their results post-render, but there are definitely edge cases here and plenty of tradeoffs. However, it's the best solution we have currently since there is no great way to useMapHooks(item => useQuery(item), items). That would be really great, but trust me, I've been down that road and while I did get something to work more or less, it ended up complicating my code much more than I expected. For the time being, React Query will likely not get the feature you're talking about, since the library itself uses hooks, it's bound by the same mechanics you are and would require massive amounts of rearchitecting to even get somewhat close to what you're describing. The return on investment would not be worth it and would likely degrade the rest of the library in both performance, size and API complexity.

To solve your specific problem for today, I would suggest three possible solutions:

  1. Be okay with multiple columns info being requested even though you only need one. Adjust your memoization/consumption of those column infos to only update if they are new. This will keep things drastically simple and probably let you move forward faster.

  2. Compose your column info fetcher queries into multiple components that don't render anything and instead pass them a prop that allows them to report their results back up to the parent component, then compose their results in the parent component into a single array of columns.

  3. Create your own little "cache" to hold your list of already-fetched column information, then combine your fetching logic into a single query. Use your custom cache object to fill in the slots in that array when the data is available and also keep it up to date by clearing the cache as often as you see fit. I would consider this a last resort, since you would essentially start managing your own custom cache, which is exactly what React Query is meant to do for you. If you do get here, I would suggest weighing the benefits your getting with React Query here overall. It may be one edge case where React Query's caching/fetching strategy isn't a good fit, which is fine.

Hope this helps!

https://github.com/tannerlinsley/react-query/issues/138#issuecomment-589709270

like image 128
Michał Mielec Avatar answered Sep 20 '22 22:09

Michał Mielec