Comments (18)
There are a couple things happening here, so I'm going to share some background that will hopefully help.
persistor.purge()
will clear the storage provider (e.g.,localStorage
), but it doesn't clear the in-memory cache, and it doesn't stop persistence from happening again.persistor.remove()
will stop persistence from happening again, but doesn't clear the storage provider or in-memory cache.client.resetStore()
will clear the in-memory cache and refetch all queries, but it has no effect on the persistor.
I regret how convoluted the interaction of these concerns is, and it's something we ought to resolve in Apollo Client 3.0. But, until then, here's the order of events I would advise for a logout:
// User clicks 'log out'.
// First: do whatever is necessary in your app to invalidate/clear out the user's session.
// Then do the following:
persistor.pause(); // Pause automatic persistence.
persistor.purge(); // Delete everything in the storage provider.
// If there are views visible that contain data from the logged-out user,
// this will cause them to clear out. It also issues a bunch of network requests
// for data that likely won't be available anymore since the user is logged-out,
// so you may consider skipping this.
client.resetStore();
// Redirect user to login page.
// At this point, the logged out user may close the tab/app.
// If they do, everything should be good: the storage provider will remain cleared,
// and no prior data will be visible upon next use.
// Let's assume the user logs in.
// First: do whatever is necessary to set the user's session.
// Next: you absolutely must reset the store. This will clear the prior user's data from
// memory and will cause all of the open queries to refetch using the new user's session.
client.resetStore();
// Resume cache persistence. The cache storage provider will be empty right now,
// but it will written with the new user's data the next time the trigger fires.
persistor.resume();
Again, I realize how convoluted this is, but login/session management is generally a convoluted thing, because there are hundreds of ways to do it, and it varies quite a bit between native apps vs. single-page apps vs. server-rendered apps.
Perhaps in the future, we could build an Apollo package for managing sessions (and thus Apollo could coordinate all of these actions).
from apollo-cache-persist.
Note there is now a client.clearStore()
function which does not refetch queries.
from apollo-cache-persist.
@jamesreggio this is good info, it would be great to promote your code to the docs and also give and example of usage in a demo app, because this is an extremely common use case
from apollo-cache-persist.
This code below works, it can be cleaned up, but it double checks a few items to ensure itβs cleared.
The setTimeout ensures an empty persist key gets cleared also, and clears the console from any noise.
SafeStorage is localstorage it just does some extra checks for device etc.
import { safeStorage } from '../data/safeStorage/safeStorage'
import client from '../data/apollo'
const allStorageKeys = storage =>
storage && typeof storage === 'object' && Object.keys(storage)
const blacklist = [
'access_token',
'id_token',
'nonce',
'expires_at',
'email',
'sub',
'r_persist',
'tid',
'uid'
]
const whitelist = []
const logoutUser = async ({ history, ...props }) => {
try {
let b_i = blacklist.length
while (b_i--) {
safeStorage.removeItem(blacklist[b_i])
}
const remaining = allStorageKeys(safeStorage)
if (remaining && remaining.length) {
let r_i = remaining.length
while (r_i--) {
if (whitelist.indexOf(remaining[r_i]) === -1) {
console.warn(
'logoutUser() - removing non-whitelisted item:',
remaining[r_i]
)
safeStorage.removeItem(remaining[r_i])
}
}
}
try {
// clear apollo client cache/store
if (client && typeof client.resetStore === 'function') {
client.resetStore()
}
} catch (e) {
console.error('err client', e)
}
// clear console in case any app messages
typeof console.clear === 'function' && console.clear()
// clear stores again after delay
setTimeout(() => {
try {
let b_i_2 = blacklist.length
while (b_i_2--) {
safeStorage.removeItem(blacklist[b_i_2])
}
// clear apollo client cache/store
if (client && typeof client.resetStore === 'function') {
client.resetStore()
}
typeof console.clear === 'function' && console.clear()
} catch (e) {
console.error('err client', e)
}
}, 2000)
} catch (e) {
// if error is caught, try to just clear all localStorage items
console.error('err 1', e)
try {
const k = allStorageKeys(safeStorage)
if (k && k.length) {
k.forEach(o => safeStorage.removeItem && safeStorage.removeItem(o))
}
if (client && typeof client.resetStore === 'function') {
client.resetStore()
}
} catch (e2) {
console.error('err 2', e2)
}
}
}
export default logoutUser
from apollo-cache-persist.
@jamesreggio thank you for the explanation. But what if user wants to switch account and wants to login immediately after log out? Can I purge the local storage and re-creating it with default client state right after user logs out?
from apollo-cache-persist.
Thanks for those details
from apollo-cache-persist.
I'm going to close this issue. If anybody needs further clarification, please don't hesitate to ask.
from apollo-cache-persist.
Check out this section: https://github.com/apollographql/apollo-cache-persist#advanced-usage
from apollo-cache-persist.
I've tried also deleting the local storage using persistor.purge() but it seems that is is never deleted or it is being repopulated
from apollo-cache-persist.
I've also tried the below steps
- persistor.remove();
- persistor.purge();
and then
3) persistor.persist()
and the localstorage is populated even though if you query the data is empty
from apollo-cache-persist.
@sce9sc Could you please create a reproduction scenario using https://codesandbox.io ?
from apollo-cache-persist.
@jamesreggio I am not sure how to access persistor
instance from a react component?
from apollo-cache-persist.
You can either import it in your file directly or use React.Context
to do so:
// cache-persistor.js
import { createContext } from "react";
import { CachePersistor } from "apollo-cache-persist";
const persistor = new CachePersistor({});
const Context = createContext(persistor);
export const CachePersistor = Context.Consumer;
// your-component.js
import React from "react";
import { CachePersistor } from "./cache-persistor";
export function YourComponent() {
return (
<CachePersistor>
{cachePersistor => (
<button
onPress={() => {
// do sth with cachePersistor here
}}
>
Press me
</button>
)}
</CachePersistor>
);
}
from apollo-cache-persist.
@jamesreggio i'm falling into the same case as @noicetoit, any advice on this ? As I see the local state is also purged, and the defaults are not set.
EDIT : actually ended up fixing it like this
if (this.cachePersistor) {
this.cachePersistor.pause();
await this.cachePersistor.purge();
await this.client.resetStore();
this.client.cache.writeData({
data: this.clientStageConfig.defaults
});
this.cachePersistor.resume();
}
from apollo-cache-persist.
A solution without using cachePersistor is client.clearStore()
which was briefly mentioned by @tamlyn above.
from apollo-cache-persist.
a combination of
client.resetStore()
and client.clearStore()
works for me!
from apollo-cache-persist.
a combination of
client.resetStore()
and client.clearStore()
works for me!
@maltenz I don't think it works as you intended. If you reload the browser, the previous cache will be restore from apollo-cache-persist, as it was never purged from there. You need to clear the memory cache (with client.clearStore()
) AND purge the persistence cache with the example provided by @rewieer.
from apollo-cache-persist.
@jamesreggio solution isn't working anymore, at least on vue-apollo, i simply can't reset the cache when the user logout and login. I even let the default code of vue CLI vue add apollo
which already have client.resetStore()
on logout
and login
method but nothing happens.
from apollo-cache-persist.
Related Issues (20)
- Feature Request: Associated time that given fields/entire cache was last updated HOT 1
- PersistMapper/PersistLink doesn't support nested cache item reference
- [Discussion] Allow for individual cache items to be saved instead of current single-key implementation HOT 1
- Don't persist @client fields? HOT 3
- AsyncStorage or window.Local storage should I use on Web? live LocalStore HOT 2
- Lazy loading cache HOT 1
- "this" has been rewritten to "undefined" HOT 1
- Why was the persistLink and persistenceMapper example removed? HOT 2
- [Request] - Please update code for MMKVStorage instance creation as per their new implementation HOT 1
- Duplication of entire / partial cache object in MMKV storage HOT 7
- [question] What's the recommended way to handle render exceptions caused by stale persisted cached data? HOT 1
- [Question] Collaborative / multiplayer caching / syncing engine? HOT 2
- Calling client.clearStore() does not reset the persistence layer HOT 4
- this.fire is not used in this case
- useLazyQuery not returning the cache value when I request on click or with delay. HOT 1
- Help for adding support apollo client next js HOT 2
- The UI is not updated when mutating the cache with writeFragment
- Is it possible not to persist data to storage if it's undefined ? HOT 4
- Garbage collection isn't working with cache persistance HOT 2
- MMKVStorage: 'Loader' is deprecated
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apollo-cache-persist.