Filter cache contents using `persistenceMapper`
masterpersistenceMapper function to the CachePersistor. This allows you to control exactly which data is written to storage.repository·master·Indexed 23 days ago
https://github.com/apollographql/apollo-cache-persistProvides simple persistence for Apollo Client 3.0 cache implementations, including InMemoryCache and Hermes, for Web and React Native platforms. It allows developers to save and restore the Apollo cache across sessions using the persistCache function or the CachePersistor class for fine-grained control. The library includes built-in wrappers for LocalStorage and AsyncStorage, and is compatible with any storage engine that follows the redux-persist API.
persistenceMapper function to the CachePersistor. This allows you to control exactly which data is written to storage.Because apollo3-cache-persist uses the same storage provider API as redux-persist, you can use any storage engine compatible with redux-persist. This includes engines like:
redux-persist-node-storageredux-persist-fs-storageredux-persist-cookie-storageTo control exactly when persistence occurs, you can provide a custom function to the trigger option.
A custom trigger must follow this signature:
(persist: () => void) => (() => void)
persist callback function.// Example: A custom trigger that persists every 10 seconds
const trigger = persist => {
// Call `persist` every 10 seconds.
const interval = setInterval(persist, 10000);
// Return function to uninstall this custom trigger.
return () => clearInterval(interval);
};
// Usage in configuration:
// persistCache({ ..., trigger: trigger });client.clearStore() method from Apollo Client. This will eventually reset the persistence layer.Install the package using npm or yarn to enable cache persistence for Apollo Client 3.0 implementations like InMemoryCache or Hermes on Web and React Native.
npm install --save apollo3-cache-persistyarn add apollo3-cache-persistTo enable persistence, pass your Apollo cache instance and a storage provider to the persistCache function.
By default, the cache contents are restored asynchronously upon initialization and persisted upon every write to the cache (using a short debounce interval).
Important: You should await the persistCache call before instantiating your ApolloClient. If you do not, queries might execute before the cache has been successfully restored from storage.
If you need to use a storage provider not listed in the natively supported providers, or if a breaking change in a supported provider prevents it from working, you can implement your own wrapper.
To implement a custom wrapper, follow the pattern established in the AsyncStorageWrapper implementation. Your wrapper must satisfy the storage provider API expected by apollo3-cache-persist (which is compatible with the redux-persist storage engine interface).
Since persistCache and persistor.restore() return a Promise, you should await the restoration before initializing your Apollo Client and rendering the application. This prevents the UI from rendering with an empty cache before the persisted data is available.
In React, the recommended pattern is to use useEffect and useState to manage the client initialization lifecycle.
import React, { useEffect, useState } from 'react';
import { ApolloClient, ApolloProvider } from '@apollo/client';
import { InMemoryCache } from '@apollo/client/core';
import { LocalStorageWrapper, persistCache } from 'apollo3-cache-persist';
const App = () => {
const [client, setClient] = useState();
useEffect(() => {
async function init() {
const cache = new InMemoryCache();
await persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage),
});
setClient(
new ApolloClient({
cache,
}),
);
}
init().catch(console.error);
}, []);
if (!client) {
return <h2>Initializing app...</h2>;
}
return (
<ApolloProvider client={client}>
{/* the rest of your app goes here */}
</ApolloProvider>
);
};
export default App;Because persisted cache data cannot be easily migrated or transformed, you should manually manage schema versions.
To handle schema changes:
SCHEMA_VERSION) in your storage.persistor.restore().persistor.purge() to clear the outdated cache and update the stored version.import AsyncStorage from '@react-native-community/async-storage';
import { InMemoryCache } from '@apollo/client/core';
import { CachePersistor, AsyncStorageWrapper } from 'apollo3-cache-persist';
const SCHEMA_VERSION = '3'; // Must be a string.
const SCHEMA_VERSION_KEY = 'apollo-schema-version';
async function setupApollo() {
const cache = new InMemoryCache({...});
const persistor = new CachePersistor({
cache,
storage: new AsyncStorageWrapper(AsyncStorage),
});
// Read the current schema version from AsyncStorage.
const currentVersion = await AsyncStorage.getItem(SCHEMA_VERSION_KEY);
if (currentVersion === SCHEMA_VERSION) {
// If the current version matches the latest version, we're good to go and can restore the cache.
await persistor.restore();
} else {
// Otherwise, we'll want to purge the outdated persisted cache
// and mark ourselves as having updated to the latest version.
await persistor.purge();
await AsyncStorage.setItem(SCHEMA_VERSION_KEY, SCHEMA_VERSION);
}
// Continue setting up Apollo as usual.
}When using AsyncStorageWrapper on Android, be aware that AsyncStorage does not support individual values in excess of 2 MB.
If your cache requires a maxSize greater than 2 MB (or if you set maxSize to false), you should avoid AsyncStorage and instead use a different provider such as MMKVStorageWrapper or redux-persist-fs-storage to prevent data loss or errors.
If you encounter the error BaseError: Couldn't read row 0, col 0 from CursorWindow..., it is likely due to the 2 MB per key limitation of AsyncStorage on Android.
Solutions:
maxSize in your configuration.react-native-mmkv-storage or redux-persist-fs-storage.On the Web, use LocalStorageWrapper to wrap window.localStorage. Ensure you await persistCache before creating your ApolloClient instance to prevent queries from running before the cache is restored.
import { InMemoryCache } from '@apollo/client/core';
import { persistCache, LocalStorageWrapper } from 'apollo3-cache-persist';
const cache = new InMemoryCache({...});
// await before instantiating ApolloClient, else queries might run before the cache is persisted
await persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage),
});
// Continue setting up Apollo as usual.
const client = new ApolloClient({
cache,
...
});