Closed BrentMifsud closed 8 months ago
Thanks for the feedback @BrentMifsud. We've had a lot of similar feedback from people on this feature, so you are not alone. We do intend to deprecate LocalCacheMutation
and allow you to make any selection set mutable in a future update.
In the mean time, the easiest way to work with this is to put the @apollo_client_ios_localCacheMutation
directive on the shared AnnouncementFragment
itself. You can use this fragment in a query, but it will also be usable for local cache mutations.
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.
Thanks for the feedback @BrentMifsud. We've had a lot of similar feedback from people on this feature, so you are not alone. We do intend to deprecate
LocalCacheMutation
and allow you to make any selection set mutable in a future update.In the mean time, the easiest way to work with this is to put the
@apollo_client_ios_localCacheMutation
directive on the sharedAnnouncementFragment
itself. You can use this fragment in a query, but it will also be usable for local cache mutations.
@AnthonyMDev Thanks for the response.
Do you have any examples of this in practice? I have added the local cache mutation directive on my fragment, but there does not seem to be any option to insert a fragment.
// from graphqlclient
func updateCachedQuery<CacheMutation: LocalCacheMutation>(
cacheMutation: CacheMutation,
mutator: @escaping (inout CacheMutation.Data) -> Void
) {
store.withinReadWriteTransaction { transaction in
try transaction.update(cacheMutation) { selectionSet in
mutator(&selectionSet)
}
}
}
Here is my codegen config (in case im missing something):
{
"schemaName" : "Redacted",
"input" : {
"operationSearchPaths" : [
"Redacted/Modules/GraphQL/Fragments/*.graphql",
"Redacted/Modules/GraphQL/Mutations/*.graphql",
"Redacted/Modules/GraphQL/Queries/*.graphql"
],
"schemaSearchPaths" : [
"Redacted/Modules/GraphQL/schema.graphqls"
]
},
"output" : {
"testMocks" : {
"none" : {}
},
"schemaTypes": {
"moduleType": {
"embeddedInTarget": {
"name": "Redacted"
}
},
"path": "Redacted/Modules/GraphQL/Generated/"
},
"operations" : {
"inSchemaModule": {}
}
},
"options": {
"selectionSetInitializers" : {
"operations": true,
"namedFragments": true,
"localCacheMutations" : true
},
"deprecatedEnumCases": "include",
"schemaDocumentation": "include",
"warningsOnDeprecatedUsage": "include",
"conversionStrategies": {
"enumCases": "camelCase"
},
"pruneGeneratedFiles": true
}
}
Ah, I see. This is still a bit difficult to do. Which is why we want to make the changes I mentioned above.
Check out the docs here. You'll want to use the updateObject(ofType:withKey:) function. Since you are actually trying to append the new announcement to a list of announcements, you'll want the
announcements` field in your mutable fragment.
fragment AnnouncementsListFragment @apollo_client_ios_localCacheMutation on Query {
announcements(locationId: $locationID) {
...AnnouncementFragment
}
}
When mutating the cache, you'll need to know the cache ID of the entity that has the announcements
field on it. But in your case, it's just on the root query, which has the cache key QUERY_ROOT
. You'll also need to pass in the correct locationID
variable.
Try this:
var myNewAnnouncement: AnnouncementFragment
store.withinReadWriteTransaction { transaction in
transaction.updateObject(
ofType: AnnouncementsListFragment.self,
withKey: "QUERY_ROOT",
variables: ["locationID": "myLocationID"]
) { (announcements inout AnnouncementsListFragment)
announcements.append(myNewAnnouncement)
}
}
There is definitely a lot to be desired with the current APIs for this. Hopefully this will get you where you need to be for now, but we definitely want to improve on this.
Ahhh I see. I never thought of making an array into a fragment. Will try that.
Use case
Today if I want my query to have a local cache mutation, I need to do the following:
The result of this is that codegen creates duplicate types:
If I ever wanted to use a local cache mutation to insert a new item, I can't simply do:
instead I have to do the following:
Alternatively, I can result to using the
_fieldData
or__data
initializers to do this in one line, but this is not type safe and can fail.Describe the solution you'd like
Ideally, the code gen should be smart enough to use a single type for both the local cache mutation and the query, so that it is easy to perform cache mutations. Or at the very least, generate convenience initializers in the cache mutations that can utilize the query data types.
Perhaps any queries marked with
@apollo_client_ios_localCacheMutation
should have an equivalent query and cache mutation generated together with the same types.