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.

Confusing pagination result with keyArgs in FieldPolicy

See original GitHub issue

I have a pagination FieldPolicy like below:

const offsetLimitPagination = (
	keyArgs = ['filter', 'sort'],
	opts = {
		concat: true,
	},
) => {
	return {
		keyArgs,
		merge(existing = makeEmptyData(), incoming, { args }) {
			let prefix = existing.edges.slice(0);
			let suffix = [];
			const incomingEdges = incoming.edges.slice(0);

			const pageInfo = {
				...existing.pageInfo,
				...incoming.pageInfo,
			};
			let edges;
			if (opts.concat) {
				edges = [...prefix, ...incomingEdges, ...suffix];
			} else {
				edges = [...incomingEdges];
			}
			const data = {
				...existing,
				...incoming,
				edges,
				pageInfo,
			};
			return data;
		},
	};
};

function makeEmptyData() {
	return {
		edges: [],
		pageInfo: {
			hasPreviousPage: false,
			hasNextPage: true,
			page: 0,
			pageSize: 100,
		},
		totalCount: 0,
	};
}

Type policy

admin__social__groups: offsetLimitPagination(undefined, { concat: false })

I have a query that looks like this:

query Admin__Social__Groups(
		$page: Int = 0
		$pageSize: Int = 10
		$filter: String
		$sort: String
		$isCursor: Boolean = false
		$before: String
		$after: String
	) {
		admin__social__groups(
			pageSize: $pageSize
			filter: $filter
			sort: $sort
			page: $page
			isCursor: $isCursor
			before: $before
			after: $after
		) {
			edges {
				node {
					...groupFragment
					status {
						hide
						review
						promoted
						autoJoin
					}
					updatedAt
				}
				cursor
			}
			pageInfo {
				...basePageInfoFragment
			}
			totalCount
		}
	}

I call fetchMore({ variables: { page: 1 } })

When I use default keyArgs ['filter', 'sort'], the pagination works as expected. But when I use keyArgs

[
	'page',
	'before',
	'after',
	'filter',
	'sort',
	'pageSize',
	'isCursor',
];

which feels more correct, bc all keys influence outcome, pagination stops working. The data is retrieved and the merge function does get processed correctly, but the screen doesn’t update. No rerendering occurs.

Intended outcome: If something is returned from the merge function, it should be rendered.

Actual outcome: Query doesn’t rerender. The old result remains isn’t replaced. My guess is that the cache key processing gets confused because of the undefined values? The array that leads to failure does include a changed key (page). Whereas the default only contains undefined keys or ['sort','filter'] (unused).

My guess is that the cache key is not calculated correctly. Or that I misunderstand how this is supposed to work. Whenever any of the parameters passed as keyArgs actually contains a value in the query, merge completes without rerendering and essentially fails.

How to reproduce the issue: See above

Versions rc.10

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
benjamncommented, Jul 6, 2020

I think you have a misunderstanding of what keyArgs are for. You do not need to include args in keyArgs just because they influence the outcome. You should only include arguments that identify completely separate instances of the field data, such as a search query whose results have nothing to do with the results of other search queries. By including args like sort and filter in keyArgs, you’re missing out on the opportunity to maintain an unsorted, unfiltered, authoritative list, which is then sorted or filtered (or whatever) by the read function. Including more key arguments just means your data will be more fragmented, and you will have less opportunity to reuse a single combined copy of the data. From a glance, none of the arguments you mentioned belong in keyArgs—again, not because they aren’t important to the outcome, but because keyArgs can only use the arguments to separate the data, whereas a read function can actually interpret the arguments and return different views of the same underlying data. In principle, read and merge functions can take full responsibility for interpretation of arguments, so you never really need keyArgs (that is, you can always get away with using keyArgs: false). It’s just useful sometimes to move certain arguments into keyArgs so that read and merge don’t have to worry about them.

1reaction
mschipperheyncommented, Jul 9, 2020

So, if I understand all of this correctly, implementing a read function basically presumes you want to manipulate data from the cache in an intelligent way. Blindly copying that got me into trouble here then. I should just not have a read function and just use a merge function.

I’m also noticing as I remove the read function that the use of keyArgs doesn’t seem to matter anymore. With the read function I was having issues with two different queries showing the same results if I didn’t add e.g. a userId as a keyArg.

I still think this is odd and prob shouldn’t happen or perhaps should show some kind of warning “Two identical cache results have different cache keys. Check your type policy” or something along those lines. But for now, I’m good. Thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Key arguments in Apollo Client - Apollo GraphQL Docs
Using the keyArgs API. We recommend reading Core pagination API before learning about considerations specific to keyArgs configuration. The Apollo Client cache ...
Read more >
React Apollo Client - query results mixing up in cache
We have to pass keyArgs explictly when relayStylePagination or similar pagination is used. A keyArgs: ["type"] field policy configuration ...
Read more >
Infinite scrolling using field policy InMemoryCache
My infinite scroll page is for media. I'm getting all media from a specific user (profile) and returning the results… over and over...
Read more >
Apollo Cache in a Nutshell - E.Y. - Medium
Through the use of relationships (primary keys, foreign keys) and constraints, we can enforce unique data getting added to the database only.
Read more >
relaystylepagination keyargs - tr.fr.edu.vn 'da Ara
Note that the relayStylePagination function generates a field policy with a ... Confusing pagination result with keyArgs in FieldPolicy #6537 github.com ...
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