T
TanStack10mo ago
genetic-orange

Refetch a query with new variables but keep data from previous results as well

From my question, is this possible, please ? It looks achievable "without" react-query itself but maybe there is a built-in function to do this
16 Replies
genetic-orange
genetic-orangeOP10mo ago
For more context : I have a paginated list of discussions. the discussions array is mapped into a discussionsIds array I want to query the notifications with this discussionsIds variable, so my backend can query notifications accordingly. As I load more discussions, I also want to load notifications for these new discussionsIds...therefore I need to keep the data from previous discussionsIds variable, but also get the data for the new variable value
ambitious-aqua
ambitious-aqua10mo ago
This works pretty much out of the box. The params you send to your backend can be used as query keys. When those keys change, it creates a new cache value. The old cache value is under the previous keys. https://tanstack.com/query/latest/docs/framework/react/guides/paginated-queries
genetic-orange
genetic-orangeOP10mo ago
but then the old results won't be accessible into the same query data? they would be replaced with results from new variable, right ? my query data result won't look like : [...oldData, ...newData] ?
ambitious-aqua
ambitious-aqua10mo ago
I see, yeah you can manually push new data if you need that: in queryFn:
const newData = await fetch();
const oldData = queryClient.getQueryData(['discussionIdKey'])
queryClient.setQueryData(['discussionIdKey'], [...oldData, ..newData])
const newData = await fetch();
const oldData = queryClient.getQueryData(['discussionIdKey'])
queryClient.setQueryData(['discussionIdKey'], [...oldData, ..newData])
Or if you're just trying to do infinite pagination, infinite queries keeps track of pages: https://tanstack.com/query/latest/docs/framework/react/guides/infinite-queries It really depends on if the cache data structure is that important to you. I think manually pushing with setQueryData is what is more common if you're dong something like a realtime chat.
genetic-orange
genetic-orangeOP10mo ago
yeah it looks like an infinite query but with changing params, so kinda tricky
ambitious-aqua
ambitious-aqua10mo ago
I'm only a fan of useInfiniteQuery when you have a cursor. Custom params can be ugly, yeah.
genetic-orange
genetic-orangeOP10mo ago
I honestly don't see how I could achieve this with an infinite query, as there is no "page" param, nor "cursor" Its just querying a notification entity that keeps a discussionId reference. So I can do something like this with prisma : prisma.notification.findMany({where: {discussion: {id: {in: discussionsIds} }) Well I think I'll try to do this myself, by keeping track of old results in a state or jotai atom
ambitious-aqua
ambitious-aqua10mo ago
And you can't just use [...discussionIds] as a key? that would be the entire list. I think local a state manager doesn't actually help anything. If you want to keep appending to old data, the snippet I put above does the exact same thing.
genetic-orange
genetic-orangeOP10mo ago
oh yeah, sorry, its very late here and I read badly your snippet 👍
ambitious-aqua
ambitious-aqua10mo ago
No worries, I use that pattern all the time. You can freely think of query as a key/value cache you can use however you want. For async data, I don't think there should be a need to escape hatch to another state manager.
genetic-orange
genetic-orangeOP10mo ago
its actually because I'm using react-query through tRPC and I'm not so used to dealing with query keys as its done magically by tRPC implementation so it has not even crossed my mind I could leverage this
ambitious-aqua
ambitious-aqua10mo ago
Yeah, it feels extra sometimes. But lets you build your own abstractions as needed. It's a trade off.
genetic-orange
genetic-orangeOP10mo ago
To do a follow-up, I ended doing this :
const key = getQueryKey(trpc.notifications.listUnread);
const client = useQueryClient();
const queriesData = client.getQueriesData<TNotification[]>({ queryKey: key });
const key = getQueryKey(trpc.notifications.listUnread);
const client = useQueryClient();
const queriesData = client.getQueriesData<TNotification[]>({ queryKey: key });
then flat mapping the data and we all good 👍 thanks for hinting me on query keys
like-gold
like-gold10mo ago
it definitely sounds like you want an infinite query though
As I load more discussions, I also want to load notifications for these new
your discussionId is the cursor. /discussions?from=0 -> shows everything starting from discussion 0 /discussions?from=25 -> shows discussions starting from 25 etc...
ambitious-aqua
ambitious-aqua10mo ago
I'm very confused on what this is trying to do as well prisma.notification.findMany({where: {discussion: {id: {in: discussionsIds} Is the only clue on what's actually happening. So somehow fetch('/disccusions?id=1&id=2&id=3') But the resulting data structure should be a flat array? Would really need more. My only point was to point out the options.
like-gold
like-gold10mo ago
sending multiple ids will be very hard to cache because /disccusions?id=1&id=2&id=3 and /disccusions?id=1&id=2&id=4 would be different cache keys. You'd need dataloader or something similar to combine those

Did you find this page helpful?