Invalidate cache based on variable change

Hi,

I am using ApolloClient (React) v3 in a project, with a CMS service providing a GraphQL API (which I have no control over)

All records have IDs and I use those in the queries so they can be cached.
All queries use a “locale” variable to query results in the intended language (which can be changed in the application)

The CMS is sending different results based on the language, but the IDs are the same no matter which language is requested, which cause caching issues.

Imagine the following query:

query GetSomeContent($locale: SiteLocale) {
  someContent(locale: $locale) {
    id # ID
    title # String
  }
}

Which is loaded based on the current language (handled in a context):

const { currentLanguage } = useI18n();

const { data, error, loading } = useQuery<GetSomeContentResponse, GetSomeContentVariables>(
  GET_SOME_CONTENT,
  {
    variables: {
      locale: currentLanguage.languageTag, // something like "en_GB"
    },
  },
);

Now, the first time the query is loaded, with for instance “en_GB”, I get the following results:

{
  "data": {
    "someContent": {
      "__typename": "SomeContentRecord",
      "id": "123456789",
      "title": "Hello World"
    }
  }
}

If I select a different language (for instance “fr_FR”), the query gets triggered again as expected, and I get:

{
  "data": {
    "someContent": {
      "__typename": "SomeContentRecord",
      "id": "123456789", // ID remains the same no matter which language is sent as a variable!
      "title": "Bonjour Monde"
    }
  }
}

So far, so good.

However, if I revert the language to one that was previously sent (“en_GB”), then the results come from the cache with the “wrong” language (I guess this is expected since the ID remains the same, but I have no control over that):

{
  "data": {
    "someContent": {
      "__typename": "SomeContentRecord",
      "id": "123456789",
      "title": "Bonjour Monde" // I expect "Hello World" here since $locale is "en_GB"
    }
  }
}

I am wondering what is the “best way” to handle that scenario… (while still caching results)

I can currently “workaround” by setting ApolloClient’s defaultOptions.watchQuery.fetchPolicy to cache-and-network.
Then the results will always match the correct language, but that seems “overkill” since the language is rarely expected to change, and I guess all queries would get refetched without a real need for it.

Is it somehow possible to:

  • use the “locale” variable as part of the cache key, on top of __typename and id? Though I have many types and hope I do not have to configure those manually…
  • reset the whole cache when the locale change? (not sure what potential caveats would there be?)

Thanks in advance :slight_smile:

Take a look at this, it might help I think, if I didn’t misread your post.

Configuring the Apollo Client cache - Client (React) - Apollo GraphQL Docs

Hi @Kheang_Hok_Chin, thanks, I did go through that one, I am just unsure if cache IDs can be configured with a query variable though (variable that is not part of any Type, per say)

Ok I understand, maybe you can take a look at cache.evict.

If I read here, apollo-client/cache.ts at b214dd1d31cdfe6b5477bb5887a7d9615a302b27 · apollographql/apollo-client (github.com)

It seems to indicate that you can pass args to tell it to evict a cache based on the args.
It is possible that you might need to also use the customized cache id with it, but not sure since I haven’t tested it.

So I would assume when you switch language, you would call this to evict the cache first.

Hope it helps.