Skip to content

Commit 8b7476f

Browse files
committed
feats:
Adds LocalStorageCacheProvider
1 parent 21a466c commit 8b7476f

3 files changed

Lines changed: 86 additions & 1 deletion

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "http-react",
3-
"version": "3.8.4",
3+
"version": "3.8.5",
44
"description": "React hooks for data fetching",
55
"main": "dist/index.js",
66
"scripts": {
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
'use client'
2+
3+
import React from 'react'
4+
import { defaultCache, FetchConfig, useIsomorphicLayoutEffect } from '../'
5+
6+
let isCacheHydrated = false
7+
8+
const loadFromLocalStorage = () => {
9+
if (typeof localStorage !== 'undefined') {
10+
for (let key in localStorage) {
11+
try {
12+
const currentValue = localStorage.getItem(key)
13+
if (typeof currentValue !== 'undefined') {
14+
console.log({ key, currentValue })
15+
16+
defaultCache.set(key, JSON.parse(currentValue!))
17+
}
18+
} catch (error) {
19+
// Remove cache key if parsing fails
20+
localStorage.removeItem(key)
21+
}
22+
}
23+
24+
isCacheHydrated = true
25+
console.log('Cache hydration complete.')
26+
}
27+
}
28+
29+
function useCacheHydration({ instant }: { instant?: boolean }) {
30+
if (instant && !isCacheHydrated) {
31+
loadFromLocalStorage()
32+
}
33+
34+
useIsomorphicLayoutEffect(() => {
35+
if (!isCacheHydrated && !instant) {
36+
const handle = window.requestIdleCallback(loadFromLocalStorage)
37+
38+
return () => window.cancelIdleCallback(handle)
39+
}
40+
41+
return () => {}
42+
}, [instant])
43+
}
44+
45+
/**
46+
* Provider component to configure the fetch library with a persistent cache.
47+
* Uses in-memory cache (defaultCache) for fast access and localStorage (storage)
48+
* for persistence, with asynchronous writes and deferred hydration.
49+
*/
50+
export function LocalStorageCacheProvider({
51+
children,
52+
instant
53+
}: React.PropsWithChildren<{ instant?: boolean }>) {
54+
useCacheHydration({ instant })
55+
56+
return (
57+
// @ts-expect-error
58+
<FetchConfig
59+
cacheProvider={{
60+
get(k) {
61+
return defaultCache.get(k)
62+
},
63+
64+
set(k, v) {
65+
defaultCache.set(k, v)
66+
67+
queueMicrotask(() => {
68+
localStorage.setItem(k, JSON.stringify(v))
69+
})
70+
},
71+
72+
remove(k) {
73+
defaultCache.remove?.(k)
74+
75+
queueMicrotask(() => {
76+
localStorage.removeItem(k)
77+
})
78+
}
79+
}}
80+
>
81+
{children}
82+
</FetchConfig>
83+
)
84+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export {
5757

5858
export { FetchConfig, SSRSuspense } from './components/server'
5959
export { SSRSuspense as Suspense } from './components/server'
60+
export { LocalStorageCacheProvider } from './components/LocalStorageCacheProvider'
6061

6162
export {
6263
queryProvider,

0 commit comments

Comments
 (0)