I have a getTracks
query that will fetch track data, and takes a handful of arguments for sorting/filtering (limit, offset, search, sort, order). Unfortunately, Apollo caches all of these separately, so when an item is deleted in one view, the user changes the sort order and the deleted item is still there (because it's in the cache for a different set of arguments).
This is the getTracks
query along with the relevant input type (in my server-side AppSync schema):
input SelectOptions {
limit: Int
offset: Int
sort: String
order: String
search: String
}
type Query {
getTracks(options: SelectOptions): TrackList!
}
type TrackList {
total: Int!
items: [Track!]!
}
In the Vue client, the query looks like this:
query GetTracks($options: SelectOptions) {
getTracks(options: $options) {
total
items {
id
name
runtime
createdAt
metadata {
trackNum
trackName
artistName
albumName
year
}
}
}
}
The first time the table is shown, the items load up and display fine (default sort order is createdAt/desc). If I sort by createdAt/asc, a network request is made to fetch the results, and they show up fine. Now, if I delete one of the records, and then sort by createdAt/desc again, the deleted item is shown since it's pulling it from the cache.
Is there no way in Apollo to have it intelligently go through and remove (or add/modify) items from the cache even though the query has different arguments? I did try the @connection
directive as documented here, but it just made it so sorting the table had no effect (it wouldn't fetch from the server at all).
I'm completely stuck, and ready to just disable caching altogether because it doesn't seem to work in real-world scenarios. How can I keep the default cache-and-network
policy, but get my tables to behave properly when data is changed?
Unfortunately, this issue has been brought up before and there's not a good existing solution for it. The biggest problem is that neither the client nor the cache expose any method for fetching all requests for a given query -- if you had that information, you could iterate through the requests and update the cache appropriately.
The next best thing you can do is utilize apollo-link-watched-mutation. The link lets us effectively identify one or more queries that will need to be updated per mutation, but it uses operation names to identify the queries (and which mutations should trigger them). This way, you don't even need to know the relevant variables to update a query -- you just need to name your operations consistently.
new WatchedMutationLink(
cache,
{
SaveTodo: {
TodoList: ({ mutation, query }) => {
// update logic here
}
}
}
)
One downside to this approach is that you lose the ability to define your update
logic on a per-component basis. However, you can also get around that limitation by using differently named mutations.