2

So I have an app with React, GraphQL and urql. I have a query that returns data (called readMeanings), and I have pagination (with a "Load more" button).

The problem is this: because of my pagination, when I reverse the sorting (from DESC to ASC), the sorted data is appended to what I had before, kind of like the "Load more" button is supposed to work.

The data looks like this (it would show 1 2 3 after 10 9 8 when I click "Load more"):

DESC: | ASC:
10    | 10
9     | 9
8     | 8
("Load more")
7     | 1
6     | 2
5     | 3

When I delete my cache pagination logic, it displays correctly as 1 2 3, but I obviously want to keep the pagination.

I'm using an urql's local resolver for the pagination cache update:

resolvers: {
  Query: {
    readMeanings: cursorMeaningPagination(),
  },
},

The query readMeanings accepts limit, cursor, used for pagination, and sorting (which contains orderBy, basically SQL's ORDER BY). These inputs are included in the field keys for different versions of the readMeanings query fields (see below). The query returns hasMore, which is used to hide/show the "Load more" button and meanings, which are the Meaning records themselves.

On the server side, changing orderBy works correctly.

My cache update logic is this (taken from Ben Awad's fullstack tutorial, around 7h 14m):

const cursorMeaningPagination = (): Resolver => {
  return (_parent, fieldArgs, cache, info) => {
    const { parentKey: entityKey, fieldName } = info; // entityKey is a query, fieldName is readMeanings

    const allFields = cache.inspectFields(entityKey); // This gives us all queries
    const fieldInfos = allFields.filter((info) => info.fieldName === fieldName); // This gives us all readMeanings queries in cache
    const size = fieldInfos.length;
    if (size === 0) {
      return undefined;
    }
    const fieldKey = `${fieldName}(${stringifyVariables(fieldArgs)})`;
    const isInCache = cache.resolve(
      cache.resolve(entityKey, fieldKey) as string,
      "meanings"
    ); // If given query is in cache
    let hasMore = true;
    const results: string[] = [];
    info.partial = !isInCache; // Do partial return if not in cache
    // For each particular cached query that we care about
    fieldInfos.forEach((fi) => {
      const key = cache.resolve(entityKey, fi.fieldKey) as Entity; // Get query's field key (includes specific args)
      const data = cache.resolve(key, "meanings") as string[]; // key like: 'posts({"limit":10})'
      const _hasMore = cache.resolve(key, "hasMore");
      if (!_hasMore) {
        hasMore = _hasMore as boolean; // If _hasMore is false
      }
      results.push(...data);
    });
    return { __typename: "PaginatedMeanings", hasMore, meanings: results };
  };
};

I see that data is taken from the cache, and appended to results, and those are meanings.

This must be really simple, but I can't guess what exactly I have to do to.

Any help would be appreciated!

vls9
  • 113
  • 10

0 Answers0