diff --git a/package.json b/package.json index 2b12b4e..c6e28d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-react", - "version": "3.8.4", + "version": "3.8.5", "description": "React hooks for data fetching", "main": "dist/index.js", "scripts": { diff --git a/src/components/LocalStorageCacheProvider.tsx b/src/components/LocalStorageCacheProvider.tsx new file mode 100644 index 0000000..c10213e --- /dev/null +++ b/src/components/LocalStorageCacheProvider.tsx @@ -0,0 +1,84 @@ +'use client' + +import React from 'react' +import { defaultCache, FetchConfig, useIsomorphicLayoutEffect } from '../' + +let isCacheHydrated = false + +const loadFromLocalStorage = () => { + if (typeof localStorage !== 'undefined') { + for (let key in localStorage) { + try { + const currentValue = localStorage.getItem(key) + if (typeof currentValue !== 'undefined') { + console.log({ key, currentValue }) + + defaultCache.set(key, JSON.parse(currentValue!)) + } + } catch (error) { + // Remove cache key if parsing fails + localStorage.removeItem(key) + } + } + + isCacheHydrated = true + console.log('Cache hydration complete.') + } +} + +function useCacheHydration({ instant }: { instant?: boolean }) { + if (instant && !isCacheHydrated) { + loadFromLocalStorage() + } + + useIsomorphicLayoutEffect(() => { + if (!isCacheHydrated && !instant) { + const handle = window.requestIdleCallback(loadFromLocalStorage) + + return () => window.cancelIdleCallback(handle) + } + + return () => {} + }, [instant]) +} + +/** + * Provider component to configure the fetch library with a persistent cache. + * Uses in-memory cache (defaultCache) for fast access and localStorage (storage) + * for persistence, with asynchronous writes and deferred hydration. + */ +export function LocalStorageCacheProvider({ + children, + instant +}: React.PropsWithChildren<{ instant?: boolean }>) { + useCacheHydration({ instant }) + + return ( + // @ts-expect-error + { + localStorage.setItem(k, JSON.stringify(v)) + }) + }, + + remove(k) { + defaultCache.remove?.(k) + + queueMicrotask(() => { + localStorage.removeItem(k) + }) + } + }} + > + {children} + + ) +} diff --git a/src/index.ts b/src/index.ts index 5560c5c..cbcd1cc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,7 @@ export { export { FetchConfig, SSRSuspense } from './components/server' export { SSRSuspense as Suspense } from './components/server' +export { LocalStorageCacheProvider } from './components/LocalStorageCacheProvider' export { queryProvider,