By default, the field's existing array is completely replaced by the incoming array.
In my case, that's fine. I have an entities: [Entity!]! field which is an array type containing Entity objects. I'm performing a mutation that updates entities on the EntityParent parent type, but I get the following warning each time a mutation on EntityParent completes and EntityParent is refetched:
console.warn
Cache data may be lost when replacing the entities field of a EntityParent object.
This could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.
To address this problem (which is not a bug in Apollo Client), define a custom merge function for the EntityParent.entities field, so InMemoryCache can safely merge these objects:
existing: [
{ __ref: 'Entity:1' },
{ __ref: 'Entity:2' },
{ __ref: 'Entity:3' },
{ __ref: 'Entity:4' },
{ __ref: 'Entity:5' },
[length]: 5
]
incoming: [
{ __ref: 'Entity:2' },
{ __ref: 'Entity:3' },
{ __ref: 'Entity:4' },
[length]: 3
]
For more information about these options, please refer to the documentation:
* Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers
* Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects
In my case, it's absolutely fine for incoming to completely replace existing, just like the docs say:
Merging arrays
...
By default, the field's existing array is completely replaced by the incoming array.
However, why do I get the warning then?
The warning goes away if I add a dummy custom merge function like this:
But again, given the documentation, Apollo should already completely ignore existing and replace it with incoming by default, right?
The docs don't say that we'll get a warning if we don't specify a custom merge function and keep the default behaviour. I find this a bit confusing 🤔 .
Is the warning always logged as long as we have an array type without a custom merge function?
const childTypenames: string[] = [];
// Arrays do not have __typename fields, and always need a custom merge 👈👈👈👈👈
// function, even if their elements are normalized entities.
if (!isArray(existing) && !isArray(incoming)) {
[existing, incoming].forEach((child) => {
const typename = store.getFieldValue(child, "__typename");
if (typeof typename === "string" && !childTypenames.includes(typename)) {
childTypenames.push(typename);
}
});
}
invariant.warn(
`Cache data may be lost when replacing the %s field of a %s object.
Then, if arrays always need a custom merge function, why isn't that written explicitly in the docs?
Hello 👋 ,
I've a question about the merging of array types in the Apollo cache mentioned in the docs:
https://www.apollographql.com/docs/react/caching/cache-field-behavior/#merging-arrays
It says:
In my case, that's fine. I have an
entities: [Entity!]!
field which is an array type containingEntity
objects. I'm performing a mutation that updatesentities
on theEntityParent
parent type, but I get the following warning each time a mutation onEntityParent
completes andEntityParent
is refetched:In my case, it's absolutely fine for
incoming
to completely replaceexisting
, just like the docs say:However, why do I get the warning then?
The warning goes away if I add a dummy custom merge function like this:
But again, given the documentation, Apollo should already completely ignore
existing
and replace it withincoming
by default, right?The docs don't say that we'll get a warning if we don't specify a custom merge function and keep the default behaviour. I find this a bit confusing 🤔 .
Is the warning always logged as long as we have an array type without a custom merge function?
Is this the behaviour you're trying to explain here? 👉 https://github.com/apollographql/apollo-client/blob/285b2d9c7bc9e9a1893a8705fc8ac2971225ea8a/src/cache/inmemory/writeToStore.ts#L842
Then, if arrays always need a custom merge function, why isn't that written explicitly in the docs?
Thank you.