94

I'm using apollo-client, apollo-link and react-apollo, I want to fully disable cache, but don't know how to do it.

I read the source of apollo-cache-inmemory, it has a config argument in its constructor, but I can't build a dummy storeFactory to make it works.

Jacky Lee
  • 1,232
  • 1
  • 9
  • 11
  • 2
    Checkout [fetchPolicy](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-fetchPolicy) and set it to `network-only`. – Robin Wieruch Feb 01 '18 at 19:19

4 Answers4

191

You can set defaultOptions to your client like this:

const defaultOptions: DefaultOptions = {
      watchQuery: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'ignore',
      },
      query: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'all',
      },
    }

const client = new ApolloClient({
    link: concat(authMiddleware, httpLink),
    cache: new InMemoryCache(),
    defaultOptions: defaultOptions,

});

fetchPolicy as no-cache avoids using the cache.

See https://www.apollographql.com/docs/react/api/core/ApolloClient/#defaultoptions

Omar Dulaimi
  • 846
  • 10
  • 30
Irvin Chan
  • 2,587
  • 2
  • 15
  • 20
  • Is this working for you? I have a query called `getRandom` and i'm trying to call it 5 times to get 5 random things, but all of them end up being the same. I have an array of queries (which are essentially all the same) that I'm mapping to get multiple `Query` components, but all the data is identical. – Brian Glaz May 17 '18 at 04:47
  • 1
    Read @duske's answer, it's correct. I don't know why this is married correct, it shouldn't be. Docs: https://www.apollographql.com/docs/react/advanced/caching.html#ignore – BrewMate Mar 14 '19 at 01:30
  • 2
    I think in almost all use cases it is probably better to disable the cache ONLY on some queries. @Anuj answer below is probably a better solution. – Elemental Jul 10 '19 at 09:31
  • 2
    Not sure why this is marked as a correct answer since it is NOT working. DefaultOptions is not working in Apollo for a very long time and it is still not fixed. – paradox37 Mar 27 '20 at 13:19
  • @IrvinChan how long apollo client save the response in caching ? – Ajay S Aug 20 '20 at 07:18
  • 1
    Works great with apollo 3. Thank you! – Omar Dulaimi Aug 21 '21 at 10:38
  • @paradox37 Are you certain it doesn't work in new Apollo versions? I just tried in Apollo v3.5.0, and it works great (fixed the unwanted caching I was hitting). Perhaps you responded before an update/fix to the answer's code? – Venryx Jan 14 '23 at 04:52
56

Actually, setting fetchPolicy to network-only still saves the response to the cache for later use, bypassing the reading and forcing a network request.

If you really want to disable the cache, read and write, use no-cache. Which is "similar to network-only, except the query's result is not stored in the cache."

Take a look at the official docs: https://www.apollographql.com/docs/react/data/queries/#configuring-fetch-logic

Bruno Peres
  • 2,980
  • 1
  • 21
  • 19
duske
  • 734
  • 6
  • 8
39

I would always suggest not to disable inbuild caching feature from apollo client. Instead you can always set fetchPolicy: 'network-only' for an individual queries. Something like this

<Query
    query={GET_DOG_PHOTO}
    variables={{ breed }}
    fetchPolicy='network-only'
>
 {({ loading, error, data, refetch, networkStatus }) => {
   ...
 }}
</Query>

While fetching data with this Query, it would always do a network request instead of reading from cache first.

Anuj
  • 941
  • 8
  • 20
  • 9
    Could it be possible to know why it is not recommended to disable Apollo client's cache? – Strider Oct 25 '19 at 21:10
  • 4
    solution I was working on in some edge cases with "fetchPolicy: 'network-only'" was still storing data in cache, and in concurrent cases was not showing the latest data, which was not what users wanted. It depends on the case, but my personal recommendation is 'no-cache' if you want to display the latest state from server all the time. It could be set per individual request or per whole client. – domingo Mar 01 '20 at 23:03
  • 1
    Sometimes its usefull to reset apollo cache: const client = useApolloClient(); someHandler =()=>{ client.resetStore(); } – northernwind Aug 02 '21 at 09:29
  • 1
    Another use case where I still want cache on. I have a UI that does many queries where a cache is useful, but there is one query that I need to run periodically to tell me when a status has changed--having caching for that one has caused me to miss the change. – Andrew Allaire Apr 14 '23 at 16:07
0

While the answer by Irvin Chan did manage to disable the caching behavior of Apollo, I found through profiling that it doesn't actually completely disable it; behind the scenes, it is still adding content to the cache, it's just that the cache is not being used.

This was a problem in my case, because the caching behavior itself was causing a noticeable performance impact on my app. (~1s of processing overhead, over a heavy data-loading period of ~20s, ie. ~5% of the cpu-time wasted)

To fix this, I created this empty alternative to InMemoryCache:

import {ApolloCache, NormalizedCacheObject} from "web-vcore/nm/@apollo/client.js";

const emptyCacheObj = {};
export class VoidCache extends ApolloCache<NormalizedCacheObject> {
    read(options) { return null; }
    write(options) { return undefined; }
    diff(options) { return {}; }
    watch(watch) { return ()=>{}; }
    async reset() {} // eslint-disable-line
    evict(options) { return false; }
    restore(data) { return this; }
    extract(optimistic) { return emptyCacheObj; }
    removeOptimistic(id) {}
    batch(options) { return undefined as any; }
    performTransaction(update, optimisticId) {}
    recordOptimisticTransaction(transaction, optimisticId) {}
    transformDocument(document) { return document; }
    transformForLink(document) { return document; }
    identify(object) { return undefined; }
    gc() { return [] as string[]; }
    modify(options) { return false; }
    readQuery(options, optimistic?) { return null; }
    readFragment(options, optimistic?) { return null; }
    writeQuery(opts) { return undefined; }
    writeFragment(opts) { return undefined; }
    updateQuery(options, update) { return null; }
    updateFragment(options, update) { return null; }
}

And I connected it to Apollo client, like so:

apolloClient = new ApolloClient({
    // replace InMemoryCache with VoidCache, because even a "not used" InMemoryCache can have noticeable overhead
    cache: new VoidCache(),
    // these config-changes might not be necessary, but I've kept them anyway
    defaultOptions: {
        watchQuery: {
            fetchPolicy: "no-cache",
            errorPolicy: "ignore",
        },
        query: {
            fetchPolicy: "no-cache",
            errorPolicy: "all",
        },
    },
});

It seems to be working well so far (avoiding the perf-loss), but I'll update this answer if there's something wrong with it and it needs tweaking.

(Note: The structure of apollo-client's cache has changed over time. My answer above only shows the working structure as of @apollo/client version 3.7.15. Check answer history if you need the structure for older versions: 3.5.0-beta.4.)

Venryx
  • 15,624
  • 10
  • 70
  • 96