I am working on building a site at the moment that, among other things, allows you to see a table of financial transactions. This table is infinite scrolling and continues to get pages of transactions are you scroll.
query UserTransactionSummary(
$userId: ID # will use context user id if one not provided
$filters: TransactionSummaryInput
) {
userTransactionSummary(userId: $userId, filters: $filters) {
transactions {
id
amount {
formatted
raw
}
cardDetails {
displayName
id
}
# more data...
}
}
}
# TransactionSummaryInput type
input TransactionSummaryInput {
startDate: DateType
endDate: DateType
filter: String
walletId: ID
transactionStatus: [TransactionStatus]
transactionType: [TransactionType]
limit: Int
offset: Int
}
This query is paginated using the following typePolicy:
const cacheConfig: InMemoryCacheConfig = {
typePolicies: {
Query: {
fields: {
userTransactionSummary: {
keyArgs: [
"userId",
"filters",
["filter", "walletId", "startDate", "endDate", "transactionType"],
],
merge(existing = {}, incoming, { args }) {
const offset = args?.filters?.offset || 0
const transactions = existing?.transactions ? existing?.transactions?.slice(0) : []
for (let i = 0; i < incoming?.transactions?.length; ++i) {
transactions[offset + i] = incoming.transactions[i]
}
return { ...existing, ...incoming, transactions }
},
},
},
// other typePolicies...
},
},
}
As the transactions are being accessed through this userTransactionSummary
query, which is where the arguments are received, the typePolicy
is defined under the global "Query"
key. This is a quirk of the way the api has been provided and is not easily changeable.
Clicking on a transaction opens a modal allowing to see the transaction history between yourself and the user you transacted with. The data for the modal is fetched with the following query:
query UserTransactionHistory(
$userId: ID # will use context user id if one not provided
$secondaryUserId: ID!
$filters: TransactionSummaryInput
) {
userTransactionHistory(
userId: $userId
secondaryUserId: $secondaryUserId
filters: $filters
) {
transactions {
id
date
isOutgoing
originalAmount {
formatted
}
}
}
}
The issue i’m having is that calling the UserTransactionHistory
query is causing the cache for the UserTransactionSummary
query to be invalidated. Here’s an example scenario:
- Open up the page with the transactions list. 10 results are loaded in using the
UserTransactionSummary
query. - as you scroll down additional batches of 10 results are loaded in using
fetchMore
. - Once you’re a few pages down (with say 40 results) you click one of the results to open the history modal.
- The history modal opens causing the
UserTransactionHistory
query to be called - The 40 cached results in the list of transactions are purged and reset to the initial 10
Worth Noting
- adding console.logs to the merge functions of both queries typePolicies shows that when the
UserTransactionHistory
query is first called, the merge function for theUserTransactionSummary
query is run. - Using
fetchPolicy: "no-cache"
on theUserTransactionHistory
query avoids the issue
Hoping someone may be able to explain this behaviour (provided it’s expected?) and maybe explain what the best way to navigate it is.
Tried:
- different typePolicies
- different merge functions
- different fetch-policies
- briefly looked at @connection directives