T
TanStack•2y ago
foreign-sapphire

Recommendation on storing list data as is and by id with one server side response

After reading through the deprecation post on onSuccess for useQuery, I'm having a hard time wrapping my head around how to massage a single response from my API into multiple query keys. I have a number of JSON APIs that return back a list of Widgets that the user has in their account. We fetch them all in one go and each JSON object of a widget returns a unique id for that widget. There are routes that require all widgets and some that focus on a single Widget by ID in that list. Ex. [ { "widgetId": "1", ... }, { "widgetId": "2", ... }] etc In what I think is the ideal data layout, we want a list of widgets easily retrievable from key ["widgets"] and then a key for each widget ["widgets", "123yea"] to satisfy the two access use cases without having to iterate over the list of widgets looking for the one we want. I have previously achieved this using the onSuccess callback and setQueryData to iterate over the list of Widgets and set each one by id.
export const useAccountWidgets = () => {
const queryClient = useQueryClient();
return useQuery({
queryKey: ["widgets"],
queryFn: getMeMyWidgetsFromTheAPI,
staleTime: hours(6),
onSuccess: (data) =>
// push all this data down to the individual caches
(data || []).forEach((i) =>
queryClient.setQueryData(["widgets", i.widgetId], i)
),
});
};
export const useAccountWidgets = () => {
const queryClient = useQueryClient();
return useQuery({
queryKey: ["widgets"],
queryFn: getMeMyWidgetsFromTheAPI,
staleTime: hours(6),
onSuccess: (data) =>
// push all this data down to the individual caches
(data || []).forEach((i) =>
queryClient.setQueryData(["widgets", i.widgetId], i)
),
});
};
I look forward to your wisdom TkDodo 🙂
6 Replies
sunny-green
sunny-green•2y ago
Do you know the select option? Seems like a perfect use case
foreign-sapphire
foreign-sapphireOP•2y ago
I did not know about the select option, but wouldn't that make a new network request for each id? What I really like about the above approach is it is one network query that populates the cache with the whole list as well as having fast lookups per widget id oh i just reread it and I think i know what you're getting at, making a select anonymous function to either return all or a single widget based on the parameters to the hook, but I'm trying to avoid having to iterate the whole list when looking for a single widget by id
absent-sapphire
absent-sapphire•2y ago
A new request always depends on staleTime Looking through a list is cheap. I wouldn't over optimize
foreign-sapphire
foreign-sapphireOP•2y ago
I like to think I'm planning for the future, the data model I'm trying to achieve is like a dictionary lookup on the backend and achieve O(1) instead of O(n). I'll be disappointed to stay on v4 but it's already rock solid, thanks
absent-sapphire
absent-sapphire•2y ago
Seeding the Query Cache
With suspense for data fetching on the horizon, it is now more important than ever to make sure your cache is seeded properly to avoid fetch waterfalls.
foreign-sapphire
foreign-sapphireOP•2y ago
perfect, this i think will work, thank you for you wisdom

Did you find this page helpful?