apollo-client: APC 3: concatPagination() not working as expected
Hi Apollo team 👋 Congrats for the v3 milestone 🎉
As advised in the v3 warning, we are trying to drop the usage of updateQuery()
in favor of TypePolicy merge()
.
However, we are facing some issues with merge()
behavior.
With the following queries, where topicList
returns a TopicList
type and TopicListItem
being an union type on 3 different items types:
query getMainTopicList($completedAfter: DateTime!) {
activeTopics: topicsList(first: 200, view: ACTIVE) {
hasAfter
items {
...TopicListItem
}
}
completedTopics: topicsList(first: 25, view: COMPLETED, completedAfter: $completedAfter ) {
items {
...TopicListItem
}
}
flowsList {
items {
...FlowListItem
}
}
}
query getCompletedTopicList($after: String) {
completedTopics: topicsList(first: 50, view: COMPLETED, after: $after) {
after
hasAfter
items {
...TopicListItem
}
}
}
we use to have the following updateQuery()
along with fetchMore()
for the getCompletedTopicList
query:
updateQuery: (previousResult, { fetchMoreResult }): GetCompletedTopicListQuery => {
const previousEntry = previousResult ? previousResult.completedTopics : { items: [], __typename: 'TopicsList' };
const newTopics = fetchMoreResult ? fetchMoreResult.completedTopics.items : [];
return {
completedTopics: {
hasAfter: fetchMoreResult!.completedTopics.hasAfter || false,
after: fetchMoreResult!.completedTopics.after,
items: uniqBy([...(newTopics || []), ...previousEntry.items], 'id'),
__typename: 'TopicsList',
},
__typename: 'Query',
};
},
})
that we remplace with a TypePolicy
as it follow:
export const typePolicies: TypePolicies = {
TopicsList: {
fields: {
items: concatPagination(),
}
},
}
new pages were now ignored, only the first page remains even when fetchMore()
is called
so, we replaced concatPagination()
by the following for debug purpose:
export const typePolicies: TypePolicies = {
TopicsList: {
fields: {
items: {
merge: (existing = [], incoming) => {
console.log('existing', existing)
console.log('incoming', incoming)
return uniqBy([...existing, ...incoming], '__ref')
}
}
}
},
}
Intended outcome:
new pages fetched using fetchMore({ variables: { after: '...' } })
are added to the results
Actual outcome:
With concatPagination()
and custom merge()
new pages are ignored, only the first page remains even when fetchMore()
is called
With custom merge()
The following is happening in merge()
- initial load,
existing = []
is an empty array, we returnincoming
(the first/initial page) - when
fetchMore()
is called,merge()
is called withexisting = []
andincoming
contains the new page
When 2 happens, returning the new page does not update the Query results
- given that
topicList
is used a many places with different filters and pagination, should we use@connection()
?
Versions
System:
OS: macOS 10.15.5
Binaries:
Node: 10.17.0 - ~/.nvm/versions/node/v10.17.0/bin/node
Yarn: 1.21.1 - /Volumes/double-hd/assistant.web/node_modules/.bin/yarn
npm: 6.11.3 - ~/.nvm/versions/node/v10.17.0/bin/npm
Browsers:
Chrome: 84.0.4147.89
Safari: 13.1.1
npmPackages:
@apollo/client: ^3.0.2 => 3.0.2
apollo: ^2.21.2 => 2.21.2
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 3
- Comments: 19 (12 by maintainers)
I’m also doing something like this! Thanks! I had to keep in mind that the keyArgs are basically all the input variables of the query that if you change those, you want to completely get rid of all the existing values. So don’t include things for the pagination in the keyArgs, but do every other input argument for the query. Here is an example to merge the
elements
field for theQueryNamexxx
query with theQueryPageable
type:First of all, thanks for all of the work you all doing, I greatly appreciate it.
@benjamn I am experiencing a similar issue as @wittydeveloper, however, my use case is very simple. I am fetching paginated array of data using query params (e.g. page=2) and then simply need to concatenate the next page to the array of existing data.
For instance, the schema for the data being returned looks like
Then in
new InMemoryCache()
I have defined:I am then feeding this data into a
FlatList
in React Native, however, thedata
field is always just the first page of results andexisting
array is always[]
even thoughincoming
appears to always contain the next page of data. I have tried usingconcatPagination()
as well as amerge
function.Any thoughts on what I am doing wrong?
@benjamn
It works, thanks! 🎉 ✅
I end-up using the following:
@dylanwulf Yes, that specific page in the docs still needs an update. Sorry for the wait!
If I’m being very optimistic, there’s a chance that specifying
keyArgs
might do the trick:But please don’t take my word for it—set some breakpoints and make sure you’re following what happens when the field policy functions are executed.
Your original
updateQuery
function seems to be a bit more complicated thanconcatPagination
, so you’re definitely going to need to reproduce the relevant behavior yourself. I recommend taking the helper functions (concatPagination
,offsetLimitPagination
, etc.) as inspiration, rather than using them directly.However, since you mentioned the
@connection
directive, you should be aware that thekeyArgs
configuration is intended to replace@connection
directives entirely. In this case, your aliased fields are distinguished byargs.view
, so you’ll probably want akeyArgs: ["view"]
configuration, at the very least, to keep those lists separate in the cache.This new system is much more powerful than what you had before, but it’s important to have an accurate mental model of what’s going on. We’re happy to answer any questions that come up as you explore it!