A query is only served from cache if the same query path, with the same variables, was previously requested.
For example if you fetch all Fund
objects:
query {
funds {
id
name
}
}
Then it will store each fund in the cache in a normalised form using (by
default) the __typename
and id
properties: Fund:1
, Fund:2
, etc.
If you then fetch a single fund:
query {
fund(id: 1) {
id
name
isin
}
}
That will be a cache miss even though the Fund:1
is in the cache. That's
because Apollo doesn't know how the server will handle the id
argument – it
could return anything.
But if you then request:
query {
fund(id: 1) {
id
name
}
}
Even though this exact query has not been run before (it doesn't request
isin
), it is a cache hit because Apollo knows that the query previously
returned Fund:1
and it has all the requested fields in the cache.
On the other hand:
query {
fund(id: 1) {
id
name
market
}
}
Would be a cache miss because it doesn't have the market
property.
Apollo Client doesn't make any assumptions about what mutations do, but it does cache the return values just the same as for queries.
So if you were to request:
mutation {
setFundName(name: "New name") {
id
name
}
}
Then Apollo would update the cache with whatever the mutation returned such that a future execution of:
query {
fund(id: 1) {
id
name
}
}
Would return the new name.
That's why it's really important to always query the ID of a type and for mutations to query any fields which they change.
Remember that every object is a type in GraphQL:
query {
user {
id
nationalInsuranceNumber
address {
addressLine1
postcode
}
}
}
Here the nested address
is its own type. But it has no id
property so it
can't be cached under its own key. Instead Apollo caches it inside the
associated user object.
But that has implications for mutations:
mutation {
setAddress(address: { addressLine1: "New St", postcode: "A1" }) {
addressLine1
postcode
}
}
Because the address has no ID, Apollo can't update the cache. Which means the user query above has a stale address.
There are ways to tell Apollo Client to refetch queries in the background, but it's better to use IDs whenever possible.
Note that the ID
type has no effect on caching behaviour.