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

Calling client.clearStore() does not reset the persistence layer #504

Open
markedwards opened this issue Oct 3, 2023 · 4 comments
Open

Comments

@markedwards
Copy link

The FAQ states:

In some cases like user logout we want to wipe out application cache. To do it effectively with Apollo Cache Persist please use client.clearStore() method that will eventually reset persistence layer.

This does not appear to work. Data remains in AsyncStorage, and is restored by persistCache().

@wodCZ
Copy link
Collaborator

wodCZ commented Oct 3, 2023

The eventually could be the key here. To forcefully clear the storage, call persistor.purge() as illustrated in the example:

const clearCache = useCallback(() => {
if (!persistor) {
return;
}
persistor.purge();
}, [persistor]);

client.clearStorage() clears the apollo client storage (sets it to an empty object), but in order to write this new state to your storage, persist has to be called on cache-persist. That is controlled by the trigger option, and if you use background trigger, the new empty state isn't persisted until you background your app.

@markedwards
Copy link
Author

Okay, that makes sense, but I think it would be helpful if the FAQ mentioned this detail. Its very easy to read that FAQ, come away with the impression that the persistence is purged on clearStore(), and unexpectedly have very incorrect behavior (that is a bit difficult to triage as such as well).

A variant that seems to work well for me is:

useEffect(() => {
  return client.onClearStore(async () => {
    await persistor.purge();
  });
}, []);

I think most would expect this to be the default behavior. In fact, is there actually a use-case for not purging when the store is cleared?

@wodCZ
Copy link
Collaborator

wodCZ commented Oct 4, 2023

is there actually a use-case for not purging when the store is cleared

I'm not aware of such use-case. The only reason I could think of is that purging might be an IO heavy task which could block the main thread, and the app might look frozen once the user taps on sign-out button.
That's why the trigger option exists, and there's no exception to it when it comes to persistence (such as "persist when app is in background, except for when the store is cleared, then persist immediately").

I see your point though, it's definitely a tricky situation with non-obvious behaviour. Would you mind submitting a PR rewording the FAQ?

@AngelRmrz
Copy link

What if i have a external logout hook, like this one:

import { client } from '@/apollo';
import useAuthStore from '@/state/auth.state';
import useUserStore from '@/state/user.state';

export const useLogout = () => {
	const clearAuthData = useAuthStore((s) => s.clearAuthData);
	const clearUserData = useUserStore((s) => s.clearUserData);
	const handleLogout = async () => {
		clearUserData();
		clearAuthData();

		client?.restore({});
	};

	return {
		handleLogout,
	};
};

How can you export the persistor from the initial config that looks like this:

import React, { useEffect, useState } from 'react';
import { CachePersistor, MMKVWrapper } from 'apollo3-cache-persist';
import { client } from './client.apollo';
import { apolloStorage } from '@/storage';
import { ApolloProvider } from '@apollo/client';

export const CustomApolloProvider: React.FC<React.PropsWithChildren> = ({
	children,
}) => {
	const [isSetClient, setClient] = useState(false);

	useEffect(() => {
		async function init() {
			const cache = client?.cache;
			let newPersistor = new CachePersistor({
				cache,
				storage: new MMKVWrapper(apolloStorage),
				trigger: 'background',
				debug: __DEV__,
			});
			await newPersistor.restore();
			setClient(true);
		}
		init();
	}, []);

	if (!isSetClient) {
		return null;
	}
	return <ApolloProvider client={client}>{children}</ApolloProvider>;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants