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.

Fetchmore is not using cache

See original GitHub issue

When using pagination and doing a fetchMore request the cache is not used to read data,

While data is already in the cache and having implementations for ‘read’ and ‘merge’ field policies, it looks like the ‘fetchMore’ is not using the typePolicy ‘read’ function and direcly does a network request. Also the fetchPolicy is not used, for example if you set it to ‘cache-only’, fetchmore is doing network requests.

It’s kinda like the example from the documentation:

const FeedData({ type = "PUBLIC" }) {
  const [limit, setLimit] = useState(10);
  const { loading, data, fetchMore } = useQuery(FEED_QUERY, {
    variables: {
      type: type.toUpperCase(),
      offset: 0,
      limit,
    },
  });

  if (loading) return <Loading/>;

  return (
    <Feed
      entries={data.feed || []}
      onLoadMore={() => {
        const currentLength = data.feed.length;
        fetchMore({
          variables: {
            offset: currentLength,
            limit: 10,
          },
        }).then(fetchMoreResult => {
          // Update variables.limit for the original query to include
          // the newly added feed items.
          setLimit(currentLength + fetchMoreResult.data.feed.length);
        });
      }
    />
  );
}

Sometimes if you scroll 500 items with a continuous scroll implementation, which loads 500 items in the cache, the component gets unmounted, and mounts again, you do not want all the 500 items to show at once because the rendering could be slow. I want to just to show the initial 10 items, and “fetchMore” from the cache or network (if it’s not in the cache), while you scroll for more items. so in the typePolicy I have something like:

const policy = {
      Query: {
        fields: {
          feed: {
            keyArgs: ['type'],
            merge: {
              // merge from offsetLimitPagination
            },
            read(existing, { args }) {
              if (!args || !existing || !(args.limit >= 0)) {
                return existing;
              }
              if (existing.length >= args.limit + (args.offset ?? 0)) {
                return existing.slice(args.offset ?? 0, args.limit ?? existing.length);
              }
              // not enough data
            },
          },
        },
      },
    };

But ‘read’ is never called when using fetchmore and always does a network call even though all the data is in the cache for the first 500 items.

Apollo version 3.3

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
robertsmitcommented, Dec 10, 2020

@awlevin I had also this problem. My current solution is to generate some typePolicies based on the schema. New arguments to fields are generated in the type policies automatically. But offcourse, a negated keyArgs would be nice. Something like excludedKeysArgs. Then the field key should be constructed with argnames included and sorted by argname.

3reactions
benjamncommented, Dec 11, 2020

@robertsmit If you have some way to detect the event of navigating back to the component, you should be able to call setLimit(10) to reset the window.

The fetchMore method sends a separate request that always has a fetch policy of no-cache, which is why it doesn’t try to read from the cache first.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Advanced topics on caching in Apollo Client
To reset the cache without refetching active queries, use client. ... You can use the fetchMore function to update a query's cached result...
Read more >
Graphql - Apollo Client/ React - Cache - fetchMore doesn't ...
It is not a field to customize the cache but a variable. ... Instead of fetchMore use refetch inside useEffect and pass there...
Read more >
Use fetchMore and merge field policies to dynamically load ...
For this, we'll start off by looking at the fetchMore utility, that is provided by ... Use reactive variables to hold local client...
Read more >
How to implement infinite scroll with Apollo client's fetch more ...
The most important part is cache which can be avoid un necessary data fetching from server side. This library is very useful because...
Read more >
Advanced topics on caching - Client (React)
Sometimes it makes sense to not use the cache for a specific operation. ... fetchMore can be used to update the result of...
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