Spaces:
No application file
No application file
File size: 2,346 Bytes
c20f20c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 'use client';
import { useState, useRef, useCallback, useEffect } from 'react';
interface UseDraftCacheOptions {
key: string;
debounceMs?: number;
}
interface UseDraftCacheReturn<T> {
cachedValue: T | undefined;
updateCache: (value: T) => void;
clearCache: () => void;
}
export function useDraftCache<T>({
key,
debounceMs = 500,
}: UseDraftCacheOptions): UseDraftCacheReturn<T> {
const [cachedValue] = useState<T | undefined>(() => {
if (typeof window === 'undefined') return undefined;
try {
const raw = localStorage.getItem(key);
if (raw !== null) {
return JSON.parse(raw) as T;
}
} catch {
/* ignore parse errors */
}
return undefined;
});
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const pendingValueRef = useRef<T | undefined>(undefined);
const keyRef = useRef(key);
useEffect(() => {
keyRef.current = key;
}, [key]);
const flushPending = useCallback(() => {
if (timerRef.current !== null) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
if (pendingValueRef.current !== undefined) {
try {
localStorage.setItem(keyRef.current, JSON.stringify(pendingValueRef.current));
} catch {
/* ignore quota errors */
}
pendingValueRef.current = undefined;
}
}, []);
const updateCache = useCallback(
(value: T) => {
pendingValueRef.current = value;
if (timerRef.current !== null) {
clearTimeout(timerRef.current);
}
timerRef.current = setTimeout(() => {
timerRef.current = null;
try {
localStorage.setItem(keyRef.current, JSON.stringify(value));
} catch {
/* ignore quota errors */
}
pendingValueRef.current = undefined;
}, debounceMs);
},
[debounceMs],
);
const clearCache = useCallback(() => {
if (timerRef.current !== null) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
pendingValueRef.current = undefined;
try {
localStorage.removeItem(keyRef.current);
} catch {
/* ignore */
}
}, []);
// Flush pending write on unmount
useEffect(() => {
return () => {
flushPending();
};
}, [flushPending]);
return { cachedValue, updateCache, clearCache };
}
|