69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import { useState, useCallback } from 'react';
|
|
|
|
const PREFIX = 'kcg.';
|
|
|
|
/**
|
|
* localStorage 연동 useState — JSON 직렬화/역직렬화 자동 처리.
|
|
* 새 키가 추가된 Record 타입은 defaults와 자동 머지.
|
|
*/
|
|
export function useLocalStorage<T>(key: string, defaults: T): [T, (v: T | ((prev: T) => T)) => void] {
|
|
const storageKey = PREFIX + key;
|
|
|
|
const [value, setValueRaw] = useState<T>(() => {
|
|
try {
|
|
const raw = localStorage.getItem(storageKey);
|
|
if (raw === null) return defaults;
|
|
const parsed = JSON.parse(raw) as T;
|
|
// Record 타입이면 defaults에 있는 키가 저장값에 없을 때 머지
|
|
if (defaults !== null && typeof defaults === 'object' && !Array.isArray(defaults)) {
|
|
return { ...defaults, ...parsed };
|
|
}
|
|
return parsed;
|
|
} catch {
|
|
return defaults;
|
|
}
|
|
});
|
|
|
|
const setValue = useCallback((updater: T | ((prev: T) => T)) => {
|
|
setValueRaw(prev => {
|
|
const next = typeof updater === 'function' ? (updater as (prev: T) => T)(prev) : updater;
|
|
try {
|
|
localStorage.setItem(storageKey, JSON.stringify(next));
|
|
} catch { /* quota exceeded — 무시 */ }
|
|
return next;
|
|
});
|
|
}, [storageKey]);
|
|
|
|
return [value, setValue];
|
|
}
|
|
|
|
/**
|
|
* Set<string>용 localStorage 연동 — 내부적으로 Array로 직렬화.
|
|
*/
|
|
export function useLocalStorageSet(key: string, defaults: Set<string>): [Set<string>, (v: Set<string> | ((prev: Set<string>) => Set<string>)) => void] {
|
|
const storageKey = PREFIX + key;
|
|
|
|
const [value, setValueRaw] = useState<Set<string>>(() => {
|
|
try {
|
|
const raw = localStorage.getItem(storageKey);
|
|
if (raw === null) return defaults;
|
|
const arr = JSON.parse(raw);
|
|
return Array.isArray(arr) ? new Set(arr) : defaults;
|
|
} catch {
|
|
return defaults;
|
|
}
|
|
});
|
|
|
|
const setValue = useCallback((updater: Set<string> | ((prev: Set<string>) => Set<string>)) => {
|
|
setValueRaw(prev => {
|
|
const next = typeof updater === 'function' ? updater(prev) : updater;
|
|
try {
|
|
localStorage.setItem(storageKey, JSON.stringify(Array.from(next)));
|
|
} catch { /* quota exceeded */ }
|
|
return next;
|
|
});
|
|
}, [storageKey]);
|
|
|
|
return [value, setValue];
|
|
}
|