question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

What kind of Apollo Client Type Policy for infinite scrolling and paged search both?

See original GitHub issue

I recently updated the apollo client package in my work to use version 3, and some things I can’t quite grasp just yet. Like defining type policy globally per query name. Here’s my issue, at work we have a search query, an offset based one, and it’s used in very different UI contexts. We have views that are table like with lots of paged data, and then we have infinite scroll type of feeds.

I have found that a single type policy for query search does not really quite support this. Here is our type policies:

typePolicies: {
  Query: {
    fields: {
      search: {
        keyArgs: (args, context) => {
          const keyArgs = ['ascendingSort', 'input', 'sortField', 'size'];
          if (context.field?.alias?.value === 'pagedSearch') {
            keyArgs.push('from');
          }
          return keyArgs;
        },
        merge: (existing, incoming, { args }) => {
          const start = args?.from || 0;
          if (!existing?.hits?.length) return incoming;

          const { hits, total, maxScore } = incoming;

          const mergedHits = existing?.hits ? existing?.hits?.slice(0) : [];
          hits.forEach((hit, i) => {
            mergedHits[start + i] = hit;
          });

          return {
            ...existing,
            hits: mergedHits,
            total,
            maxScore,
          };
        },
      },
    },
  },
};

The hacky part here is that we are using field alias:

pagedSearch: search(input: $input from: $from) for search query and pushing offset variable to the keyArgs of paged queries, so user gets fresh results when they change the table’s page.

if (context.field?.alias?.value === 'pagedSearch') { keyArgs.push('from'); } This does get the job done for now, but I want to know how would one implement a single type policy for these type of queries?

I have asked this question on stack overflow a while a go, but no answers yet https://stackoverflow.com/questions/68157953/what-kind-of-apollo-client-type-policy-for-infinite-scrolling-and-paged-results

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:5
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
SkinyMonkeycommented, Sep 5, 2021

By the way : I feel like when an alias is setup on a query, apollo should use it instead of the original query name.

1reaction
benjamncommented, Dec 1, 2021

I honestly think returning everything from the read function (ignoring offset and limit) is the most flexible option for both infinite scroll and paginated navigation, because then you can use application/UI-level logic to slice the big array into chunks for pagination (in a part of your code where you probably have enough context to make that choice), and you don’t have to keep updating the offset and limit of the original query each time you fetch new data, and both queries can consume the same underlying list of data (rather than maintaining separate lists in the cache).

This difference between paginated and non-paginated read functions is discussed here in the docs. I’m specifically recommending the non-paginated approach.


If you’re not sold on the one-big-list philosophy, and you want to keep using @connection, keep reading for some additional thoughts…

Since keyArgs is intended to replace @connection, I would hope you can just use keyArgs, but I admit @connection can be useful to inject arbitrary key information, and is conveniently already understood by most GraphQL tooling (unlike other directives or arguments you might make up).

While InMemoryCache does support @connection in the absence of keyArgs, prior to AC3.5, there was a pitfall where providing keyArgs would cause @connection to be ignored (see #8659). Thanks to #8678 (released in v3.5), it’s now possible to include information from any directives (or variables) in your keyArgs array:

new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        search: {
          keyArgs: ["query", "@connection", ["key"]],
          merge(...) {...},
        },
      },
    },
  },
})

This configuration will produce field keys like search:{"query":"...","@connection":{"key":"searchInfinite"}}, so the @connection(key) information is handled sort of like an argument passed to the field. You should not need to pass a filter argument to @connection, since that’s what the other strings in keyArgs represent.

Read more comments on GitHub >

github_iconTop Results From Across the Web

What kind of Type Policy for infinite scrolling and paged ...
I have found that a single type policy for query search, does not really quite support this. Here is our type policies: typePolicies:...
Read more >
Infinite Scroll With Apollo Client 3 - Trevor Blades
Infinite scroll is a web design technique that loads more content as the user scrolls towards the end of the loaded content. It...
Read more >
How to implement infinite scroll with Apollo client's fetch more ...
3. Set up your apollo client in index.js like below. You need to set cache type policy to use offset based pagination by...
Read more >
Pagination - Apollo GraphQL - w3resource
There are also two ways for displaying paginated data: discrete pages, and infinite scrolling. In this tutorial, we'll cover the technical ...
Read more >
Infinite scrolling with GraphQL - LogRocket Blog
This creates the need to paginate. Pagination in a GraphQL API allows clients, or our frontend, to query lists of items in parts...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found