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.
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
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.
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 {}"