0
I’m using @apollo/client version 3.7.3 in a react.js, typescript application. After fetching a list of objects from the server, some values are removed from the cache spontaneously!
So when the client gets the data from the server, it stores them in the cache to be used in the UI and the cache version is different from the actual server response.
I tried to narrow down the problem and remove unrelated stuff to focus just on the problem and here is my observation:
- The data is 100% correct on the backend and gets received by the web client correctly in the response.
- I isolated this query call to make sure no other parts of the application update/mutate its cache.
- It’s definitely a cache problem, since when I set the fetchPolicy to "no-cache" it works perfectly fine.
- It’s definitely not a rendering problem or any other DOM-related issue since I tried just to log it on the console and didn’t even use it on the DOM.
- It only happens for this particular object type and this specific endpoint call. So in every other place, everything works just fine!
- It happens just for some fields that are optional on the graphql schema. When I change them to non-optional, everything works just fine!
1 Answer
Reset to default
0
After doing lots of trial and error, making some experiences, and reading lots of Apollo-related docs I have found the source of the issue: normalization
So basically apollo client does a set of normalization by default on your cache. And in my case, it removed some data right after storing them in the cache without asking me!
It’s recommended to disable normalization for objects that are not getting updated frequently. Which was the case for me. It was data that didn’t get updated that often and my strategy was to prevent server calls as much as I could and rely on cache instead.
So I disabled the normalization based on this document:
https://www.apollographql.com/docs/react/caching/cache-configuration/#disabling-normalization
You just need to define a new TypePolicy and set keyFields to false. Then pass it to your InMemoryCache. Similar to this:
const cache = new InMemoryCache({
typePolicies: {
<YOUR_TYPE_NAME>: {
keyFields: false,
}
},
...
});
const cachePersistor = new CachePersistor({
cache,
...
});