# Results for different keyArgs value queries are getting passed to/mixed up in merge type policy

**URL:** <https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249>\
**Category:** Client SDKs\
**Tags:** client\
**Created:** [May 11, 2023, 12:43am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249 "2023-05-11T00:43:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnnywang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/johnnywang/32/4268_2.png) [@johnnywang](https://community.apollographql.com/u/johnnywang)\
**Post date:** [May 11, 2023, 12:43am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/1 "2023-05-11T00:43:59Z")

</div>

I have a pagination query that takes in an `offset`, `limit`, and `category` field, the last of which is used to filter results by a certain type. I’ve implemented the type policy for this query using the default `offsetLimitPagination` helper [as mentioned here](https://www.apollographql.com/docs/react/pagination/offset-based/), and infinite scroll within the same query does seem to be working.

In my app, this query is used to display a list of results for a particular category, with an option at the top of the screen to switch between categories (active and expired). I’ve specified `category` as a `keyArg`, but despite this, when I switch between categories, I see the results of the previous category at the top of my new list (i.e. if active has 5 results and expired has 3, switching from active → expired will show 8 results instead of 3)

When using [the actual source](https://github.com/apollographql/apollo-client/blob/main/src/utilities/policies/pagination.ts#L33-L49) for the `merge` function from above, I’m seeing that `existing` is populated with the prior query’s results, _even when the `category` keyArg changes_. I was under the impression that if the keyArg values change, they’re stored separately, in which case any change in keyArg should result in `existing` being undefined. Am I fundamentally misunderstanding how this works?

If that’s _not_ how it’s supposed to work, how can I modify the `merge` such that it only merges the results for non-keyArg differences (`limit` and `offset`)?

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [May 11, 2023, 1:16am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/2 "2023-05-11T01:16:48Z")

</div>

Hey @johnnywang 👋

This seems suspect and I agree I wouldn’t expect this to happen. Would you be able to provide a small runnable example, or paste what the contents of your cache are? You can either use Apollo’s DevTools or spit out a JS object using `client.cache.extract()`. I’m curious if your cache keys are the same or different in the cache itself for the paginated data.

---

<div class="post-metadata">

**Author:** ![johnnywang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/johnnywang/32/4268_2.png) [@johnnywang](https://community.apollographql.com/u/johnnywang)\
**Post date:** [May 12, 2023, 12:28am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/3 "2023-05-12T00:28:55Z")

</div>

Hey @jerelmiller!

A runnable example would be difficult, unfortunately. Extracting the cache, it does appear that each individual item is cached under different keys:

Here’s what the merge function gets when the (React Native) screen first queries against the active filter:

```auto
 LOG -----------args {"input": {"category": "ACTIVE", "limit": 8, "offset": 0}}
 LOG -----------existing undefined
 LOG -----------incoming [{" __ref": "GroupOffer:fa7a5617-0bc6-46fd-bef3-395661538c44"}, {"__ ref": "GroupOffer:f73fb306-0250-4805-b1d1-890d3c6de960"}, {" __ref": "GroupOffer:96ef3c51-aa02-4118-aa4c-18fa754ad122"}, {"__ ref": "GroupOffer:372cc59c-8a53-456a-9e93-beb3017b4f80"}, {"__ref": "GroupOffer:fc1be3a5-baa9-4fff-a48b-d637130e5008"}]

```

Which corresponds to the cache values here:

```auto
GroupOffer:96ef3c51-aa02-4118-aa4c-18fa754ad122: { ...offerDetails }
GroupOffer:372cc59c-8a53-456a-9e93-beb3017b4f80: { ...offerDetails }
GroupOffer:f73fb306-0250-4805-b1d1-890d3c6de960: { ...offerDetails }
GroupOffer:fa7a5617-0bc6-46fd-bef3-395661538c44: { ...offerDetails }
GroupOffer:fc1be3a5-baa9-4fff-a48b-d637130e5008: { ...offerDetails }

```

When I switch over to the inactive filter, this is what merge gets (notice that the existing is populated and set to the previous active cache keys):

```auto
 LOG -----------args {"input": {"category": "INACTIVE", "limit": 8, "offset": 0}}
 LOG -----------existing [{" __ref": "GroupOffer:fa7a5617-0bc6-46fd-bef3-395661538c44"}, {"__ ref": "GroupOffer:f73fb306-0250-4805-b1d1-890d3c6de960"}, {" __ref": "GroupOffer:96ef3c51-aa02-4118-aa4c-18fa754ad122"}, {"__ ref": "GroupOffer:372cc59c-8a53-456a-9e93-beb3017b4f80"}, {"__ref": "GroupOffer:fc1be3a5-baa9-4fff-a48b-d637130e5008"}]
 LOG -----------incoming [{" __ref": "GroupOffer:3ce37911-8a6b-4bfa-937b-5481149e6579"}, {"__ ref": "GroupOffer:7630f3c6-130a-4bf5-9155-341f7047e325"}, {" __ref": "GroupOffer:f99025f2-689b-4aca-b546-61e4fa45ae5c"}, {"__ ref": "GroupOffer:ecb621a2-576b-4d8b-9623-d538fdb4ad08"}, {" __ref": "GroupOffer:41005df3-cafa-4c76-8582-6508343a8e3f"}, {"__ ref": "GroupOffer:e7edae04-5460-43af-acc9-e0476ea8d996"}, {" __ref": "GroupOffer:2af859a8-4cde-438e-9d99-18dfa936d76d"}, {"__ ref": "GroupOffer:379109a1-d666-4077-b89c-ae35d1280cd1"}]

```

And in the cache itself you see the old and new keys:

```auto
GroupOffer:2af859a8-4cde-438e-9d99-18dfa936d76d: { ...offerDetails }
GroupOffer:3ce37911-8a6b-4bfa-937b-5481149e6579: { ...offerDetails }
GroupOffer:96ef3c51-aa02-4118-aa4c-18fa754ad122: { ...offerDetails }
GroupOffer:372cc59c-8a53-456a-9e93-beb3017b4f80: { ...offerDetails }
GroupOffer:7630f3c6-130a-4bf5-9155-341f7047e325: { ...offerDetails }
GroupOffer:41005df3-cafa-4c76-8582-6508343a8e3f: { ...offerDetails }
GroupOffer:379109a1-d666-4077-b89c-ae35d1280cd1: { ...offerDetails }
GroupOffer:e7edae04-5460-43af-acc9-e0476ea8d996: { ...offerDetails }
GroupOffer:ecb621a2-576b-4d8b-9623-d538fdb4ad08: { ...offerDetails }
GroupOffer:f73fb306-0250-4805-b1d1-890d3c6de960: { ...offerDetails }
GroupOffer:f99025f2-689b-4aca-b546-61e4fa45ae5c: { ...offerDetails }
GroupOffer:fa7a5617-0bc6-46fd-bef3-395661538c44: { ...offerDetails }
GroupOffer:fc1be3a5-baa9-4fff-a48b-d637130e5008: { ...offerDetails }

```

And this is what the relevant portion of my field policy looks like:

```auto
      groupOfferQuery: {
        keyArgs: ['category'],
        merge(existing, incoming, { args, cache }) {
          console.log('-----------args', args);
          console.log('-----------existing', existing);
          console.log('-----------incoming', incoming);
          console.log('-----------cache', cache.extract());

          const merged = existing ? existing.slice(0) : [];

```

The UI does seem to be “working” now that I switched from cursor to offset pagination, but I suspect it’s only working because the offset is reset back to 0, and is overriding the sliced existing array. With cursor style, since there’s no overwrite, you end up getting old and new results.

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [May 12, 2023, 12:38am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/4 "2023-05-12T00:38:29Z")

</div>

Hey @johnnywang

The thing that sticks out to me right away is that the `category` arg is tucked under the `input` key. I’m willing to bet that the key arg thats being calculated for that field is `undefined` instead of the category value `ACTIVE` or `INACTIVE` in this case, so its likely the cache is thinking you’re trying to calculate a list from the same value (`undefined`). This would explain why you’re seeing the same set of data in both places.

If I recall correctly, you should be able to declare `keyArgs` similar to `keyFields` where you can pass a nested array to get a field inside an object. In your case, this should look like this:

```ts
keyArgs: ['input', ['category']]

```

If you’re using the `offsetLimitPagination` helper, the `keyArgs` value is the argument to that function, so it would look like this.

```auto
offsetLimitPagination(['input', ['category']])

```

Try this and see if it helps!

---

<div class="post-metadata">

**Author:** ![johnnywang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/johnnywang/32/4268_2.png) [@johnnywang](https://community.apollographql.com/u/johnnywang)\
**Post date:** [May 12, 2023, 1:06am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/5 "2023-05-12T01:06:03Z")

</div>

Oh that did it, thanks @jerelmiller! That thought crossed my mind very briefly, since I had to revise the pagination helper to account for offset not being at the top level either:

```auto
        // Modify Apollo's default offsetLimitPagination implementation since
        // we nest our args under an `input` key
        // https://github.com/apollographql/apollo-client/blob/main/src/utilities/policies/pagination.ts#L33-L49
        merge(existing, incoming, { args }) {
          const merged = existing ? existing.slice(0) : [];

          if (incoming) {
            if (args) {
              const { offset = 0 } = args.input;

```

I’m assuming there’s no way to get around that short of just copying and modifying the source like I’m doing here?

But also, that might be a worthwhile note to add to the documentation, to call out that these only work under the expectation of a certain top-level format

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [May 12, 2023, 2:08am UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/6 "2023-05-12T02:08:18Z")

</div>

Oh thats a good point that the default implementation of `offsetLimitPagination` assumes `limit` and `offset` are top-level args. Really good call on updating the documentation to mention that this utility is designed for the “common” case but you’d need to copy the implementation to account for differences. Copying the source and modifying it like you’re doing is unfortunately the best way to get this working properly in your case.

Glad to hear this fixed the issue for you!

---

<div class="post-metadata">

**Author:** ![Justin\_Gonzalez](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/justin_gonzalez/32/5359_2.png) [@Justin\_Gonzalez](https://community.apollographql.com/u/Justin_Gonzalez)\
**Post date:** [February 6, 2025, 8:48pm UTC](https://community.apollographql.com/t/results-for-different-keyargs-value-queries-are-getting-passed-to-mixed-up-in-merge-type-policy/6249/7 "2025-02-06T20:48:57Z")

</div>


