Skip to content

v4: Refetch does not use typePolicies as documented in Apollo 3 docs #1194

Open
@lucatk

Description

@lucatk

Describe the bug
Apollo 3 recommends using InMemoryCache typePolicies for cache operations for pagination instead of updateQuery on the fetchMore function.
When trying to use typePolicies with vue-apollo, the behaviour is not as intended.

To Reproduce
Steps to reproduce the behavior:

  1. Create Apollo Client using an InMemoryCache which has some typePolicies for the paginated query (define merge and read functions)
const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        paginatedField: {
          keyArgs: ['filter'],
          merge (existing = makeEmptyPaginatedData(), incoming, { args: { page = 0, count = 10 } }) {
            console.log('merge options:', page, count, 'data:', incoming);
            const start = page * count;
            const merged = existing.items.slice(0);
            for (let i = 0; i < incoming.items.length; ++i) {
              merged[start + i] = incoming.items[i];
            }
            return Object.assign({}, incoming, {
              items: merged,
              index: existing.index !== -1 && existing.index < incoming.index ? existing.index : incoming.index,
              count: merged.length,
              hasPrevious: start > 0 ? existing.hasPrevious : incoming.hasPrevious,
              hasNext: start + count < merged.count ? existing.hasNext : incoming.hasNext,
            });
          },
          read (existing, { args: { page = 0, count = 10 } }) {
            if (!existing) {
              return;
            }

            const start = page * count;
            const end = start + count;
            const items = existing.items.slice(start, end);
            const result = Object.assign({}, existing, {
              items,
              index: page,
              count: items.length,
              hasPrevious: page > 0,
              hasNext: existing.items.length > end || existing.hasNext,
            });
            console.log('read options:', page, count, 'data:', result);
            return result;
          },
        },
      },
    },
  },
});
  1. Define paginated query
const { result, fetchMore } = useQuery(
  gql`query ($page: Int, $count: Int) {
    paginatedField(filter: [...], page: $page, count: $count) {
      index
      count
      hasPrevious
      hasNext
      items {
        [...]
      }
    }
  }`,
  {
    page: 0,
    count: 10,
  },
);
  1. Load page (initial query ran with variables page=0, count=10)
  2. Call fetchMore with variables page=1, count=10
  3. Console output:
merge options: 0 10 data: [...]
read options: 0 10 data: [...]
// here fetchMore is called
merge options: 1 10 data: [...]
read options: 0 10 data: [...]

Expected behavior
Read function should be called with variables from most recent query (e.g. fetchMore call) just like merge function is called
Console would read as follows:

merge options: 0 10 data: [...]
read options: 0 10 data: [...]
// here fetchMore is called
merge options: 1 10 data: [...]
read options: 1 10 data: [...]

Versions
vue: 2.6.12
vue-apollo: @vue/[email protected]
apollo-client: 3.3.18

Additional context
Add any other context about the problem here.

Research guided me towards this Apollo issue, however I could not figure out how to apply this to solve my problem.
#1115 also seems to be similar, but didn't provide a clear solution either.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions