Apollo-client: Restore cache to its initial state

Created on 10 Jul 2018  路  3Comments  路  Source: apollographql/apollo-client

I use SSR to rehydrate the cache with initial state from the server

const cache = new InMemoryCache().restore(window.__APOLLO_STATE__)

Few mutations later, I need to hard reset the cache to its initial state. I naively tried to keep the initial store in component state and pass it to client.restore

componentDidMount () {
  this.setState({
    initState: this.props.client.extract()
  })

  handleCacheReset () {
    this.props.client.restore( this.state.initState )
  }
}

but it didn't work. Since I'm also using using apollo-link-state, I thought if I keep the cache data as defaults, maybe then I can write them when client.resetStore is called

const cache = new InMemoryCache().restore(window.__APOLLO_STATE__)
const link = withClientState({ cache })
const client = new ApolloClient({
  link, cache,
  defaults: cache.data.data
})
client.onResetStore(link.writeDefaults)

// ...when it's time to reset the store
client.resetStore()

But I only get Missing field ... in {} errors and no data gets written to the store. Worse, I can't use client.writeData since I only have the initial window.__APOLLO_STATE__. If only I could read the entire cache data, then it might be plausible, but there doesn't seem to be a readData method.

Is there a way to programmatically restore the cache to its original state?

So far the only workaround I see is re-creating the entire ApolloClient and forcefully re-rendering the tree, which is expensive and inefficient. Thoughts?

Versions

  • apollo-cache-inmemory: ^1.2.5 => 1.2.5
  • apollo-client: ^2.3.5 => 2.3.5
  • apollo-link-state: ^0.4.1 => 0.4.1
  • react-apollo: ^2.1.9 => 2.1.9

Most helpful comment

@alex996 Did you ever get a fix for this? I'm experiencing the same thing even though I'm writing my client-state defaults in an onResetStore callback. When the observable queries are re-run (after all the onResetStore callbacks finish) my cache should be in the state it's in on launch but I'm getting yellowboxes complaining about "Missing {{field}} in {}"

All 3 comments

Issues here are reserved for Apollo Client bugs. You鈥檒l have a much better chance of getting this answered in the Apollo Slack group or on Stack Overflow. Thanks!

@alex996 Did you ever get a fix for this? I'm experiencing the same thing even though I'm writing my client-state defaults in an onResetStore callback. When the observable queries are re-run (after all the onResetStore callbacks finish) my cache should be in the state it's in on launch but I'm getting yellowboxes complaining about "Missing {{field}} in {}"

I also suffered from those kind of "Missing {{field}} in {}" errors after calling .resetStore and this because .resetStore refetches your observables before you have a chance to re-write an "initialState" considering that you just purged it. However, the solution of using .clearStore wasn't exactly want I needed because I still wanted all my observables to refetch after doing the reset.

So I dived in and found client.reFetchObservableQueries which is the method run at the end of the promise chain that .resetStore uses to have a refetching ability compared to .clearStore that simply leaves that part out.

Consider trying:

await client.clearStore();
await cache.writeData({ data: defaultState });
await client.reFetchObservableQueries();

So essentially you can reset/clear your cache of all items, prepare your cache like you did upon initialisation (like with .writeData) and then invoke the end part of the .resetStore method to get all your useQuery etc observables updated again.

Was this page helpful?
0 / 5 - 0 ratings