Confusing pagination result with keyArgs in FieldPolicy
See original GitHub issueI 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:
- Created 3 years ago
- Comments:5 (2 by maintainers)
I think you have a misunderstanding of what
keyArgs
are for. You do not need to include args inkeyArgs
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 likesort
andfilter
inkeyArgs
, you’re missing out on the opportunity to maintain an unsorted, unfiltered, authoritative list, which is then sorted or filtered (or whatever) by theread
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 inkeyArgs
—again, not because they aren’t important to the outcome, but becausekeyArgs
can only use the arguments to separate the data, whereas aread
function can actually interpret the arguments and return different views of the same underlying data. In principle,read
andmerge
functions can take full responsibility for interpretation of arguments, so you never really needkeyArgs
(that is, you can always get away with usingkeyArgs: false
). It’s just useful sometimes to move certain arguments intokeyArgs
so thatread
andmerge
don’t have to worry about them.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 theread
function I was having issues with two different queries showing the same results if I didn’t add e.g. auserId
as akeyArg
.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.