Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client.resetStore() doesn't reset the store #1552

Closed
dfee opened this issue Apr 5, 2017 · 18 comments
Closed

client.resetStore() doesn't reset the store #1552

dfee opened this issue Apr 5, 2017 · 18 comments

Comments

@dfee
Copy link

dfee commented Apr 5, 2017

Intended outcome:
Props change when client.resetStore() is called.

Actual outcome:
Props do not change on client.resetStore().

How to reproduce the issue:
Checkout this minimally modified repo: https://github.com/dfee/react-apollo-error-template/tree/resetstore

Etc.
Is this intended? I assumed that resetting the store (upon logout for instance) would immediately reset apollo data. Instead it seems that if the query returns a new result, then the update occurs.

It appears this function might be more aptly named: client.refetchQueries.

@Poincare
Copy link
Contributor

Poincare commented Apr 5, 2017

client.resetStore refetches active queries on your page. This is intended behavior. If we didn't do this and just emptied out all of the information in the store, all of the active queries on your page would be broken since they wouldn't correspond to a query result in the store. This is mentioned in the relevant API documentation albeit in one sentence.

I don't think it makes sense to call this refetchQueries because it only refetches your active queries and throws away the data that isn't associated with active queries. I do agree the behavior is a bit surprising to a lot of people - maybe just having better docs around resetting the store would solve this part of the problem?

@richardgirges
Copy link

I think client.resetStore is most confusing when it comes to active queries that are contingent on authentication. When I call client.resetStore in my app after logout, what I want it to do is clear out all of my active queries' data. Instead, I get a slew of 401 auth errors from my backend due to the majority of the active queries being session-based queries.

This seems heavy-handed because I know the queries are no longer valid - I just want to empty them out.

So if client.resetStore isn't the answer to this scenario, then what is the right approach to the following workflow?

  1. User goes to app/website
  2. User logs in
  3. User views "My Purchases" page (triggers MyPurchasesQuery)
  4. User logs out
  5. How do we clear out the MyPurchasesQuery data in this case? client.resetStore will attempt to refetch the MyPurchasesQuery but the desired behavior in this scenario isn't to refetch the query, it's to dump the query's data.

I guess I'm looking for something more along the lines of a "client.emptyStore". Or maybe my general approach is wrong - any light you can shed on my plight would be greatly appreciated.

@dfee
Copy link
Author

dfee commented Apr 6, 2017

The reason I filed this ticket, the spirit of the ticket per se, is what @richardgirges has described.

@dfee
Copy link
Author

dfee commented Apr 6, 2017

@Poincare this is what the docs say:

resetStore()
Resets your entire store by clearing out your cache and then re-executing all of your active queries. This makes it so that you may guarantee that there is no data left in your store from a time before you called this method.

I am relatively new to the world of front-end, so I see everything on the front-end as a cache. When I see, "there is no data left in your store from a time before you called this method", I interpret that to mean "all Apollo data will be wiped".

Am I correct in assuming this really means:

  • all active queries (queries bound to a promise) are cleared out
  • subscriptions queries are not reset (largely an implementation detail provided from the next point)
  • components are not provided new props, or loading=true (so there's no way to signal to components that a reset has occurred).
  • all queries for visible components are re-fetched (but the components are unaware of this refetch).

Thanks!

@thebigredgeek
Copy link
Contributor

I think the problem here is confusion due to bad naming, and possibly bad docs. It might be worth while to change the name of resetStore to refetchAllQueries.

@Poincare
Copy link
Contributor

Poincare commented Apr 6, 2017

These concerns are pretty reasonable. I'm not sure if we have a good solution at the moment to clear out auth'ed data from your cache. As I mentioned, just throwing away everything in the cache isn't a reasonable solution since all active queries (i.e. those with Observables associated with them) would break.

I do think the docs don't do a great job of explaining this, especially with the second sentence. If any of you could submit a PR to fix that, that would be awesome.

I don't agree with renaming resetStore to refetchAllQueries i.e. I'm saying we can can rename it to something else, just not that. Fundamentally, only the active queries are refetched, not all of them. Secondly, in addition to refetching active queries, we do empty out the store of previous results which is not captured by the name refetchAllQueries.

@thebigredgeek
Copy link
Contributor

@Poincare well, technically you shouldn't need to clear the store if you re-fetch all queries... unless you aren't cleaning up references. Data shouldn't remain in the store if it is no longer referenced by a query / mutation entry... it should be removed so that the GC can clear up memory... and there is just no reason to leave it there since it is no longer accessible anyway. If the query references are re-built, it seems like it solves the problem of purging the cache of old now-inaccessible data, does it not?

@jacobk
Copy link

jacobk commented Apr 19, 2017

I agree that resetStore is confusing and multiple tickets have been raised both here and in react-apollo trying to reason about it's purpose and intended behavior (search "resetStore").

apollographql/react-apollo#531 was recently merged for the purpose of trying to deal with resetStore refetching queries it shouldn't but is now causing issues with refetchQueries (see apollographql/react-apollo#622).

Me like others only considered resetStore for the purpose of nuking the app on logout. In my cases there's no GraphQL when you don't have a session making my world pretty black and white (login etc. are rest apis).

I'll look into manually removing the redux-state populated by apollo-client and remove the entire client on logout and create a new client on login, optionally just skip it all and revert to refreshing the page as a last resort.

Maybe the equivalent of that should be added as client.resetClient which removes all queries followed by a resetStore?

@helfer
Copy link
Contributor

helfer commented May 2, 2017

Ok, it seems like the issue has been solved, so I'll close this. I agree with @jacobk that we could probably use a resetClient. I'd be open to merging that PR if someone would make it!

@larryranches
Copy link

Is there any best practice on resetStore() on logout since then? I also had the idea that resetStore() would reset my store and not refetch queries again like I'm seeing today.

@ghost
Copy link

ghost commented Nov 29, 2017

Are there any updates on this?

@danderson00
Copy link

Why is this closed? I don't see how the issue is resolved. We require a way to reset the client state on log out, like many others contributing to this thread. If the issue is resolved, what is the current guidance for achieving this?

@larryranches
Copy link

larryranches commented Dec 5, 2017

The way I handled this was that I am using my own redux store and have the actual ApolloStore as a single child reducer under this store. I use the redux way to actually delete the entire store via an Action that can be called in a "logout" function for example. Since the ApolloStore is a reducer in that store, it resets/wipes it.

if (action.type === actionTypes.RESET_STATE) {
    newState = undefined; // resets entire state
 }

@aroth
Copy link

aroth commented Dec 10, 2017

Running into continued issues with this as well.

@emipc
Copy link

emipc commented Feb 14, 2018

How are we supposed to reset the store if client.resetStore() is not resetting the store?

@stantoncbradley
Copy link

client.cache.reset() will actually clear the cache
vuejs/apollo#53 (comment)

@lukemadera
Copy link

@stantoncbradley I tried this but it is still refetching queries. Is this supposed to actually clear the cache and NOT refetch anything?

@pawelkoska
Copy link

pawelkoska commented Aug 29, 2018

what about exporting defaultState from index.js containing all initial states and use cache.writeData({data: defaultState}) in logout method?

index.js:
export const defaultState = { ...currentUser, ...someData, };

const stateLink = withClientState({ cache, defaults: defaultState, resolvers: {...}, }

in Logout.js:
this.props.logout(); this.props.client.cache.writeData({ data: defaultState });

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests