mikejackowski
mikejackowski

Reputation: 69

Combine offsetLimitPagination with filtering Apollo Graphql

I'm implementing a pretty advanced table (using React-Table) for a large, complex set of data. I started by following Apollo's guide implementing offset-based pagination, I got sorting to work as well. What I'm stuck at is combining that with server-side filtering.

My definition of InMemoryCache looks like this - I'm querying a field Targets:

const cache = new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          Targets: {
            ...offsetLimitPagination(),       
            read(existing, { args }): any {
              if (args && args.limit !== undefined && args.offset !== undefined) {
                return existing && existing.slice(args.offset, args.offset + args.limit);
              }
            },
          },
        },
      },
    },
  });

which is pretty much the outcome for what the guide told me to do for Pagination. My component queries backend:

const { networkStatus, error, data, fetchMore, refetch } = useQuery<GetTargetsQuery, GetTargetsQueryVariables>(GET_TARGETS, {
    ...
    notifyOnNetworkStatusChange: true,
    variables: {
      limit: tableState.pageSize,
      offset: tableState.pageNumber * tableState.pageSize,
      orderBy: tableState.orderBy,
      where: {
        _and: [initialFilters, queryFilters],
      },
    },
  });

The issue is, when I'm modifying the queryFilters and data gets refetched, I'm seeing correct data in my Network Tab in browser, but my component still reads the old data from the cache. It seems like the offsetLimitPagination hook is not exactly crafted for incorporating filtering(?).

I can't use the React-Table's built-in filtering, as it only operates on the data that has been queried (which in my case is part of the entire set). How do I modify my InMemoryCache to overwrite the data in cache if there are new filters set? Or is there a better way to tackle this or better question to ask to get this done?

Upvotes: 2

Views: 2199

Answers (1)

Leomar Amiel
Leomar Amiel

Reputation: 506

To clarify the keyArgs, you'd want to specify the keys that would connect one cache from another.

In your case, you have the variables limit, offset, orderBy & where.

So in the case of changing the limit & offset, you do not want Apollo to create a separate cache when limit & offset changes. So you leave that out of the keyArgs.

The keyArgs that you want to watch is your changes with orderBy & where. From my understanding, the new keyArgs are what you want to base your cache from. So if anything in the orderBy & where changes, you'd want Apollo to treat it as somewhat of a separate dataset.

Also, offsetLimitPagination accepts a keyArgs prop. So in terms of nested variables like the variable where, you can configure it in the keyArgs as a nested value so Apollo has an idea of what the inside of those values are.

The nested array syntax applies to the previous argument value (where).

const cache = new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          Targets: {
            ...offsetLimitPagination(["orderBy", "where", ["_and"]]),
            read(existing, { args }): any {
              if (args && args.limit !== undefined && args.offset !== undefined) {
                return existing && existing.slice(args.offset, args.offset + args.limit);
              }
            },
          },
        },
      },
    },
  });

Upvotes: 3

Related Questions