You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First, the issue I'm trying to address with this feature request was perfectly stated in 2016 in this comment:
Today, when we have a mutation that is affecting the result of a query done on another page, I'm using one of these approach:
setting fetchPolicy to cache-and-network: not ideal because you are over-fetching most of the time
using refetchQueries on the mutation: not ideal either for the reasons mentioned in Revisit refetchQueries API #419 + because when using different set of variables (like when doing pagination), it only refetched that most recently used set of variables. In addition, sometimes we just don't want to refetch because the user might not go back to the query page so it could also be over-fetching.
using updateQuery from the query and manually update the cache: most performant way to do it but it sometimes super hard or even impossible if the query is reading from an aggregation table for example.
I started to use cache.evict({ fieldName: 'example' }) but the issue is that the fieldName isn't type-safe. Therefore, I built this helper function to do this in a safe way from an array of DocumentNode (generated by graphql-codegen):
constinvalidateQueries=(cache: ApolloCache<any>,documentNodes: DocumentNode[])=>{constfieldsToInvalidate=documentNodes.flatMap((documentNode)=>documentNode.definitions.flatMap((definition)=>{if(!('selectionSet'indefinition)){return[];}returndefinition.selectionSet.selections.map((selection)=>{if('name'inselection){returnselection.name.value;}returnnull;}).filter(isPresent);}));fieldsToInvalidate.forEach((fieldName)=>{cache.evict({
fieldName,});});// I'm not yet sure if I should call `cache.gc()` here };
This is working fine on the tests I did but now I'm wondering if cache.evict() could directly accept a DocumentNode (or even an array of nodes) to evict all the fields selected by the queries (this comment was also suggesting this).
Thanks for opening the request and thanks for your patience!
This is an interesting idea, though I'd like to push back a little bit on the idea of a document-based solution. Since InMemoryCache is a normalized cache, there are scenarios that get tricky to handle. For example, what happens if you issue 2 queries that request the same field and you only invalidate one of the queries? Does it partially invalidate the other query? Should it refetch the other query because its partially invalidated? Those are things to think through as well.
I do agree with you that there should be a more robust invalidation API, but I'd prefer to use it on the field-level which fits the normalized cache paradigm more closely. In this case, invalidating a field would mark it as stale and any queries that consume that field would refetch in order to synchronize it with the server. Ideally this becomes the replacement for refetchQueries in the future.
On the TypeScript end, I'd like to see InMemoryCache accept a Schema generic type that has full knowledge of your GraphQL schema types in order to better type APIs such as type policies, cache eviction, etc. We are hoping to get something like this either in 4.0 or a minor version shortly after. I'm hoping this would alleviate some of the type safety issues that currently exist when using the cache.
First, the issue I'm trying to address with this feature request was perfectly stated in 2016 in this comment:
Today, when we have a mutation that is affecting the result of a query done on another page, I'm using one of these approach:
fetchPolicy
tocache-and-network
: not ideal because you are over-fetching most of the timerefetchQueries
on the mutation: not ideal either for the reasons mentioned in RevisitrefetchQueries
API #419 + because when using different set of variables (like when doing pagination), it only refetched that most recently used set of variables. In addition, sometimes we just don't want to refetch because the user might not go back to the query page so it could also be over-fetching.updateQuery
from the query and manually update the cache: most performant way to do it but it sometimes super hard or even impossible if the query is reading from an aggregation table for example.What I'm looking for is a way to invalidate a set of queries similar to react-query invalidateQueries.
I started to use
cache.evict({ fieldName: 'example' })
but the issue is that thefieldName
isn't type-safe. Therefore, I built this helper function to do this in a safe way from an array ofDocumentNode
(generated bygraphql-codegen
):I can then use it like this:
This is working fine on the tests I did but now I'm wondering if
cache.evict()
could directly accept aDocumentNode
(or even an array of nodes) toevict
all the fields selected by the queries (this comment was also suggesting this).Basically being able to do:
or to be even closer to
react-query
:The text was updated successfully, but these errors were encountered: