Can't get infinite loading with fetchmore to work

In the docs, I see that the terms offset and limit are used a lot. I am using keystone, which uses the terms first and skip. I am trying to make this work, but somewhere I am missing a key component.

Within my client creation, I have added a reference to offsetLimitPagination():
allComments: offsetLimitPagination(),

Then, I create my query along with variables to pass in:

const ALL_COMMENTS = gql`
  query ALL_COMMENTS($id: ID!, $first: Int, $skip: Int) {
      where: { post: { id: $id }, parentId_is_null: true }
      sortBy: id_DESC
      first: $first
      skip: $skip
    ) {
      user {
let first = 4;
let perPage = 4;

Then my useQuery statement:

    variables: {
      id: "ckracasxy75851o8vgpk909ibb",
      first: 4,
      skip: 0,

Then I have a button that activates ‘plzFetchMore’. For now, I am trying to make this work with a button, but then will upgrade it to be infinite scrolling. I need the basics figured out first. Here is what I have:

function plzFetchMore() {
    first = first + first;

      variables: {
        id: "ckracasxy75851o8vgpk909ibb",
        first: 4,
        skip: first,


So with this code, everything appears to be working perfectly. I am able to fetch 4 new results of data, but the issue is, the older data is disappearing. How can I force the older data to stay on the page? If I could run a function that takes in cache/payload, I could do it manually. However, I believe the solution is much simpler than that. Can anyone guide me?

Thank you.

Hi! Have you provided keyArgs for your paginated field? See here for more details.

In your case, I’d expect your cache declaration would need to look like this:

export default new InMemoryCache({
    typePolicies: {
        Query: {
            fields: {
                allComments: offsetLimitPagination(['where', 'sortBy']),

keyArgs defines the arguments that InMemoryCache uses to build cache objects - if you omit it, it is assumed that all arguments are part of the cache key. In that case, changing first and skip will create an entirely different cache object, which explains why your previous results disappear. If you set the keyArgs, only the specified values will be used for the cache key (where and sortBy), so changing first and skip will not cause a different cache object to be created.

Thank you for the detailed response. Are you sure about first/skip not causing a change? I just added the ‘where’ and ‘sortBy’ args to offsetLimitPagination but unfortunately did not fix it. It did however, not break it. I am not entirely sure how to proceed, given that I am still getting the same results. If I set ‘first’ value to double after every click, it refetches the entire query, which is not ideal. Any ideas?

Hmm. I would suggest checking the contents of your cache before and after changing the first value and seeing if they match your expectations. You can access the cache on the JS console using window.__APOLLO_CLIENT__.cache.extract(). Ideally, you should find only one cache object in the ROOT_QUERY for each where and sortBy permutation in there, and a change to first or skip should not create a new one. Maybe looking into that will make things clearer.

I see. All of my cache indicates that it is falling under the same query everytime. I am using Apollo dev tools and seeing queries remain the same as I fetch more results. Oddly enough, my initial query is rendering twice, one with __typename and one without. I added the __typename to my query, and it still renders twice. I am assuming this is normal, because when I fetch more the two queries remain the same without any extra adding onto it. When I go to the cache tab, they all appear as comments with the same typename. I am going to keep investigating and will update here if I find the solution.


I found the solution. Change offsetLimitPagination() to concatPagination(). Now old results are loaded through cache and are not refetched :), like how true pagination should work.