I'm upgrading my application with Apollo Client from v2 to v3 and I can't find the correct solution to the following problem.
I have a schema with a product and inside this product, a price. This price is not a simple number as it contains the duty free value, the all taxes included value and the VAT.
type Product {
id: ID
price: Price
}
type Price {
dutyFree: Float
allTaxesIncluded: Float
VAT: Float
}
In Apollo Client 2, whenever there was no explicit id or _id property, the InMemoryCache created a fallback fake identifier to normalize data, based on the path to the object.
In Apollo Client 3, this fallback fake identifier is no longer generated. Instead you have two options to handle non-normalized data. The first is to use the new TypePolicy option and indicates explicitly the data you receive should not be normalize. In that case, data will be linked to the parent normalized data.
The doc :
Objects that are not normalized are instead embedded within their parent object in the cache. You can't access these objects directly, but you can access them via their parent.
new InMemoryCache({
typePolicies: {
Price {
keyFields: false
}
}
})
All happy, I though my problem was solved. Well, wrong ... I can create a product in my app and add a price. But whenever I change an existing price, I get the following warning :
Cache data may be lost when replacing the price field of a Product object.
Because, when I get my Product after an update, the InMemoryCache does not know how to merge the field Price because no id is defined, which is the point of non-normalized data.
I know there is the second option to explicitly define a merge function for my Product.price field, but this example is a simpler version of the reality. I have a large number of fields through multiple objects which are typed Price, and manually defining a merge function for each and everyone one of them (even by externalizing the common logic in a function) is something I find quite inefficient and source of errors.
So my question is : what did I misunderstood about the keyFields: false
option and what can I do to solve this problem without having to resort to define a merge function to 50+ fields in my app ?
Thanks for the help :)