Apollo fails to merge cache on refetch call

Viewed 67

I'm trying to use the merge function for each refetch (filtering a list) but the existing value always comes undefined.

Type Policy of query that return and filter a list:

Query: {
        fields: {
            accounts: {
                keyArgs: false,
                merge(
                    existing,
                    incoming,
                    {args: {page = 1, pageSize = 20}, readField}
                ) {
                    const offset = (page - 1) * pageSize;
        
                    if (!existing?.items) {
                        return incoming;
                    }
        
                    const mergedItems = [...existing.items];
                    const existingIdSet = new Set(
                        mergedItems.map((item) =>
                            readField('externalReferenceCode', item)
                        )
                    );
        
                    const incomingItems = [...incoming.items].filter(
                        (item) =>
                            !existingIdSet.has(readField('externalReferenceCode', item))
                    );
        
                    for (let i = 0; i < incomingItems.length; ++i) {
                        mergedItems[offset + i] = incomingItems[i];
                    }
        
                    return {
                        ...existing,
                        items: mergedItems,
                    };
                },
                read(existing, {args: {page = 1, pageSize = 20}}) {
                    const offset = (page - 1) * pageSize;
        
                    if (!existing) {
                        return;
                    }
        
                    return {
                        ...existing,
                        items: existing.items?.slice(offset, offset + pageSize),
                    };
                },
            },
        },
    },

I'm doing something wrong? Checking by read function, the values pass as expected, but when call a refetch, comes empty.

For merge, the first it's the existing value. And in read, the value printed it was the existing value.

typePolicy.js:34 merge undefined {__typename: 'AccountPage', items: Array(20), totalCount: 235}
typePolicy.js:108 read {__typename: 'AccountPage', items: Array(20), totalCount: 235}
typePolicy.js:34 merge undefined {__typename: 'AccountPage', items: Array(2), totalCount: 2}
typePolicy.js:108 read {__typename: 'AccountPage', items: Array(2), totalCount: 2}

And this is the query:

const GET_ACCOUNTS = gql`
    query getAccounts($filter: String, $pageSize: Int = 20, $page: Int = 1) {
        accounts(filter: $filter, pageSize: $pageSize, page: $page) {
            items {
                id
                externalReferenceCode
                name
            }
            totalCount
        }
    }
`;
1 Answers

Had the same issue. Here's the solution: https://community.apollographql.com/t/context-overwrite-is-being-set-to-true-meaning-that-the-existing-arg-in-the-merge-function-of-apollo-cache-is-always-undefined/3090/2

there was a reasonably recent change to the default behaviour that switched context.overwrite to true for any refetch operation. The solution to this is an as yet seemingly undocumented option that can be passed to either the apollo client instantiation or the in the options to the react query hooks. The option is refetchWritePolicy: "merge" (default is “overwrite”).

Related