T
TanStack•17mo ago
exotic-emerald

How to update the state of a paged query manually?

My items are fetched from multiple sources and combined into one sorted list in a RQ store, where each source is a group, so I need to update the cache manually at the sorted index. Should I just use onSuccess to do this? how do I prevent the default append that RQ does on response? Example:
const response = ['dog', 'cat', 'bird', /* new type */ 'car', 'truck', 'ship', /* new type */ 'apple', 'orange', 'lemon']

// Then, user clicks on "load more animals" and the API will query page-2 for just animals, so cache should be updated like this:
oldDataDraft.splice(4, 0, ...newAnimals)
const response = ['dog', 'cat', 'bird', /* new type */ 'car', 'truck', 'ship', /* new type */ 'apple', 'orange', 'lemon']

// Then, user clicks on "load more animals" and the API will query page-2 for just animals, so cache should be updated like this:
oldDataDraft.splice(4, 0, ...newAnimals)
6 Replies
exotic-emerald
exotic-emerald•17mo ago
are you talking about infinite queries?
how do I prevent the default append that RQ does on response
Not sure what you mean. you need to be more precise with your question please. Best thing is a running reproduction (stackblitz, codesandbox). Not code snippets, no screenshots 🙂
exotic-emerald
exotic-emeraldOP•17mo ago
I have a bulk endpoint that returns lists from multiple backend repositories, the combined list is stored in RQ, but pagination is at the repository level, so I can't do a standard paginated query. I'm just wondering if RQ can handle it,. @TkDodo 🔮 Does that make it clearer? :))
exotic-emerald
exotic-emerald•17mo ago
not really 😅
exotic-emerald
exotic-emeraldOP•17mo ago
I have 3 APIs: 1. Owner API 2. Tenant API 3. Vendor API 1. I do Promise.all over these APIs to get a list from each one. 2. I want to store the list returned by each API into a combined list in RQ. I did that, it's easy. Now, I need to support pagination that enables me to paginate a specific API and then have RQ update the combined list correctly, since it's ordered (Owners, Tenants, Vendors). I really wish I could just make a repro of this, but I'm a bit stressed out. Sorry about that.
exotic-emerald
exotic-emerald•17mo ago
so I think this is just 3x useQuery with a single API call each and then in the ui you combine them? and then pagination happens with each query separately
exotic-emerald
exotic-emeraldOP•17mo ago
exactly I think structuralSharing might help here, but I'm unsure. I'm giving it a try. Lmk if this makes sense...
const { data: peopleDataBase, ...restQueryResults } = useInfiniteQuery(
["infinite-people-query-get-all", restQueryFilter],
{
refetchOnWindowFocus: false,
keepPreviousData: true,
queryFn: async ({ signal, pageParam }) => {
const data = await peopleApi.getAll({ ...queryFilter, page_numbers: pageParam });
if (!data || signal?.aborted) {
return null;
}
return data;
},
structuralSharing: (oldData, newData) => {
if (!oldData) {
return newData;
}

oldData?.pages.forEach((page) => {
page?.data?.dataGroups.forEach((data, index) => {
const nextData = newData.pages[newData.pages.length - 1]?.data?.dataGroups[index];

if (nextData) {
data.push(...nextData);
}
});
});

return oldData;
}
}
);
const { data: peopleDataBase, ...restQueryResults } = useInfiniteQuery(
["infinite-people-query-get-all", restQueryFilter],
{
refetchOnWindowFocus: false,
keepPreviousData: true,
queryFn: async ({ signal, pageParam }) => {
const data = await peopleApi.getAll({ ...queryFilter, page_numbers: pageParam });
if (!data || signal?.aborted) {
return null;
}
return data;
},
structuralSharing: (oldData, newData) => {
if (!oldData) {
return newData;
}

oldData?.pages.forEach((page) => {
page?.data?.dataGroups.forEach((data, index) => {
const nextData = newData.pages[newData.pages.length - 1]?.data?.dataGroups[index];

if (nextData) {
data.push(...nextData);
}
});
});

return oldData;
}
}
);
@TkDodo 🔮 Actually, nvm, it doesn't make sense as I cancelled out the pagination itself, it keeps the first page forever just keeps on updating it. 🙂 I think RQ doesn't cater to this use-case. Maybe listing from multiple sources like that is anti-pattern anyway.

Did you find this page helpful?