subscribeToMore causes the initial request to be refetched
See original GitHub issueHello,
I’m setting up a quite simple message feed on my app. There is an infinite scroll that uses the fetchMore function with a cursor pagination logic and a subscribeToMore to listen for new messages.
I can succeed to make the apollo working for fetching more OR subscription but not for both…
This is my initial query:
messageFeed(id: $id, cursor: $cursor) {
messages {
id
value
}
cursor
}
This is my merging function:
typePolicies: {
Query: {
fields: {
messageFeed: {
keyArgs: false,
merge(existing, incoming) {
let messages
if (existing) {
messages = [...existing.messages, ...incoming.messages];
} else {
messages = incoming.messages;
}
return {
cursor: incoming.cursor,
messages
}
}
}
}
}
}
So if I stop here, it is working fine. The merging is well executed and I got an infinite flow of messages while I’m scrolling down.
Here come the subscription and the issues…
This is my subscribeToMore function:
subscribeToMore({
document: NEW_MESSAGE_SUBSCRIPTION,
variables: {
discussionId: discussionID
},
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newMessage = subscriptionData.data.message;
return {
messageFeed: {
messages: [newMessage]
}
};
}
})
When a new message is posted, here what happening on the DOM:
initial 20 first messages new message from the subscription again initial 20 first messages
When debugging, I noticed the merge function is called twice.
First call (when the subscription is fired) existing => the first 20 messages already displayed in the DOM incoming => the new message from the subscription merge => the two are merged and the 21 messages are well returned.
It should stop here.
BUT then, a new graphql post (with the same variables as the initial request at page load) is coming from nowhere which cause the merge function to be called again:
existing => the 21 messages already displayed in the DOM incoming => the same 20 messages as the initial request merge => the two are merge and the 41 and returning (including 20 duplicates)
Any idea from where is coming that second call?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:12 (1 by maintainers)
Top GitHub Comments
In a situation without a pagination to deal with, setting
nextFetchPolicy: 'cache-first'
, as suggested by @LovingGarlic, works perfectly.Essentially it’s something like this:
Note in the second conditional, that I check for the existence of a
before
cursor (my pagination only goes one direction). This is to determine if the merge was triggered by afetchMore
or asubscription
as mentioned above. The notice in the last return, making sure to add the__typename
field to the returned object (this seems necessary for the cache to be updated properly), then building out thepageInfo
andedges
. A similar strategy would be needed for theupdateQuery
.