Hello! Thanks for any pointers and help – I am trying to get some nested pagination working - It seems I can get the data into the cache in the right place, but the UI does not update.
First, I request a list of paginated “Kits” from the server with the following query. Nested within the kits is a list of “Products” that is also paginated. The two inputs/variables below handle the cursor based pagination with the createdAt
field.
export const GET_KIT_PRODUCTS = gql`
query GetKitProducts(
$getKitsInput: GetKitsInput!
$getProductsInput: GetProductsInput!
) {
getKits(getKitsInput: $getKitsInput) {
data {
_id
products(getProductsInput: $getProductsInput) {
stats {
total
remaining
page
}
data {
_id
name
brand_name
retailer
createdAt
}
}
}
}
}
`;
The server sends back a list of kits and the correct pagination for both the kits and the products. I use the following TypePolicy to make sure duplicate kits and products are not added to the cache. The products are also merged under the correct kit.
Also for reference, here is the GetKitsResponse
type. The Kit
list is actually nested inside the data
property of the response.
type GetKitsResponse {
stats: Stats
data: [Kit]!
}
export const cache: InMemoryCache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
getKits: {
keyArgs: false,
merge(
existing = [] as Kit[],
incoming: GetKitsResponse,
{ args, readField }
) {
console.log("Existing", existing);
console.log("Incoming", incoming);
const merged = { ...existing };
incoming.data?.forEach((item) => {
if (item) {
merged[readField("_id", item) as string] = item;
}
});
console.log("MERGED", merged);
return merged;
},
read(existing) {
return existing && Object.values(existing);
},
},
},
},
Kit: {
fields: {
products: {
keyArgs: false,
merge(
existing = [] as Product[],
incoming: GetProductsResponse,
{ readField }
) {
const merged = { ...existing };
incoming.data?.forEach((item) => {
if (item) {
merged[readField("_id", item) as string] = item;
}
});
console.log(merged);
return merged;
},
read(existing) {
return existing && Object.values(existing);
},
},
},
}
});
On the initial render of my react component, it loads the list of X number products. I use the fetchMore function, shown below, to request X more products from a specified cursor.
const handleLoadMore = () => {
if (kitProducts && kitProducts?.length > 0) {
const remaining =
getKitProductsData?.getKits.data[0]?.products.stats?.remaining;
if (remaining && remaining > 0) {
const cursor =
kitProducts[kitProducts.length - 1] &&
kitProducts[kitProducts.length - 1]?.createdAt;
fetchMore({
variables: {
getProductsInput: {
config: {
pagination: {
reverse: true,
createdAt: cursor,
},
},
},
},
});
}
}
};
The products network request is fine, the kits do not duplicate in the cache, and the newly fetched (fetchMore) products are added to the “Kit” in the cache.
Thanks for the help, I have been stuck here for about 2 days - I really appreciate any advice ya’ll have!