diff --git a/docs/src/pages/plugins/createAsyncStoragePersistor.md b/docs/src/pages/plugins/createAsyncStoragePersistor.md index 2d23b39f1b..6556c15999 100644 --- a/docs/src/pages/plugins/createAsyncStoragePersistor.md +++ b/docs/src/pages/plugins/createAsyncStoragePersistor.md @@ -60,6 +60,10 @@ interface CreateAsyncStoragePersistorOptions { /** To avoid localstorage spamming, * pass a time in ms to throttle saving the cache to disk */ throttleTime?: number + /** How to serialize the data to storage */ + serialize?: (client: PersistedClient) => string + /** How to deserialize the data from storage */ + deserialize?: (cachedString: string) => PersistedClient } interface AsyncStorage { @@ -75,5 +79,7 @@ The default options are: { key = `REACT_QUERY_OFFLINE_CACHE`, throttleTime = 1000, + serialize = JSON.stringify, + deserialize = JSON.parse, } ``` diff --git a/docs/src/pages/plugins/createWebStoragePersistor.md b/docs/src/pages/plugins/createWebStoragePersistor.md index 31c53061cf..983ac336bf 100644 --- a/docs/src/pages/plugins/createWebStoragePersistor.md +++ b/docs/src/pages/plugins/createWebStoragePersistor.md @@ -57,6 +57,10 @@ interface CreateWebStoragePersistorOptions { /** To avoid spamming, * pass a time in ms to throttle saving the cache to disk */ throttleTime?: number + /** How to serialize the data to storage */ + serialize?: (client: PersistedClient) => string + /** How to deserialize the data from storage */ + deserialize?: (cachedString: string) => PersistedClient } ``` @@ -66,5 +70,7 @@ The default options are: { key = `REACT_QUERY_OFFLINE_CACHE`, throttleTime = 1000, + serialize = JSON.stringify, + deserialize = JSON.parse, } ``` diff --git a/src/createAsyncStoragePersistor-experimental/index.ts b/src/createAsyncStoragePersistor-experimental/index.ts index 0141229bb5..a9d43a3c76 100644 --- a/src/createAsyncStoragePersistor-experimental/index.ts +++ b/src/createAsyncStoragePersistor-experimental/index.ts @@ -14,16 +14,28 @@ interface CreateAsyncStoragePersistorOptions { /** To avoid spamming, * pass a time in ms to throttle saving the cache to disk */ throttleTime?: number + /** + * How to serialize the data to storage. + * @default `JSON.stringify` + */ + serialize?: (client: PersistedClient) => string + /** + * How to deserialize the data from storage. + * @default `JSON.parse` + */ + deserialize?: (cachedString: string) => PersistedClient } export const createAsyncStoragePersistor = ({ storage, key = `REACT_QUERY_OFFLINE_CACHE`, throttleTime = 1000, + serialize = JSON.stringify, + deserialize = JSON.parse, }: CreateAsyncStoragePersistorOptions): Persistor => { return { persistClient: asyncThrottle( - persistedClient => storage.setItem(key, JSON.stringify(persistedClient)), + persistedClient => storage.setItem(key, serialize(persistedClient)), { interval: throttleTime } ), restoreClient: async () => { @@ -33,22 +45,22 @@ export const createAsyncStoragePersistor = ({ return } - return JSON.parse(cacheString) as PersistedClient + return deserialize(cacheString) as PersistedClient }, removeClient: () => storage.removeItem(key), } } -function asyncThrottle( - func: (...args: ReadonlyArray) => Promise, +function asyncThrottle( + func: (...args: Args) => Promise, { interval = 1000, limit = 1 }: { interval?: number; limit?: number } = {} ) { if (typeof func !== 'function') throw new Error('argument is not function.') const running = { current: false } let lastTime = 0 let timeout: number - const queue: Array = [] - return (...args: any) => + const queue: Array = [] + return (...args: Args) => (async () => { if (running.current) { lastTime = Date.now() diff --git a/src/createWebStoragePersistor-experimental/index.ts b/src/createWebStoragePersistor-experimental/index.ts index 3d54e64359..130f5d9f29 100644 --- a/src/createWebStoragePersistor-experimental/index.ts +++ b/src/createWebStoragePersistor-experimental/index.ts @@ -9,17 +9,29 @@ interface CreateWebStoragePersistorOptions { /** To avoid spamming, * pass a time in ms to throttle saving the cache to disk */ throttleTime?: number + /** + * How to serialize the data to storage. + * @default `JSON.stringify` + */ + serialize?: (client: PersistedClient) => string + /** + * How to deserialize the data from storage. + * @default `JSON.parse` + */ + deserialize?: (cachedString: string) => PersistedClient } export function createWebStoragePersistor({ storage, key = `REACT_QUERY_OFFLINE_CACHE`, throttleTime = 1000, + serialize = JSON.stringify, + deserialize = JSON.parse, }: CreateWebStoragePersistorOptions): Persistor { if (typeof storage !== 'undefined') { return { persistClient: throttle(persistedClient => { - storage.setItem(key, JSON.stringify(persistedClient)) + storage.setItem(key, serialize(persistedClient)) }, throttleTime), restoreClient: () => { const cacheString = storage.getItem(key) @@ -28,7 +40,7 @@ export function createWebStoragePersistor({ return } - return JSON.parse(cacheString) as PersistedClient + return deserialize(cacheString) as PersistedClient }, removeClient: () => { storage.removeItem(key)