import { useSyncExternalStore } from 'react'
import { useRef } from 'react'
function createLocalStorageStore<T>(key: string, initialValue: T) {
let currentValue = getInitialValue(key, initialValue)
const listeners = new Set<() => void>()
function getInitialValue(key: string, initialValue: T): T {
try {
const item = localStorage.getItem(key)
return item ? JSON.parse(item) : initialValue
} catch {
return initialValue
}
}
function setValue(value: T | ((prevValue: T) => T)) {
const valueToStore = value instanceof Function ? value(currentValue) : value
currentValue = valueToStore
localStorage.setItem(key, JSON.stringify(valueToStore))
listeners.forEach((listener) => listener())
}
function subscribe(listener: () => void) {
listeners.add(listener)
const handleStorageChange = (event: StorageEvent) => {
if (event.key === key) {
currentValue = getInitialValue(key, initialValue)
listeners.forEach((l) => l())
}
}
window.addEventListener('storage', handleStorageChange)
return () => {
listeners.delete(listener)
window.removeEventListener('storage', handleStorageChange)
}
}
return {
subscribe,
getSnapshot: () => currentValue,
setValue,
}
}
function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((prevValue: T) => T)) => void] {
const storeRef = useRef(createLocalStorageStore(key, initialValue))
const value = useSyncExternalStore(storeRef.current.subscribe, storeRef.current.getSnapshot)
return [value, storeRef.current.setValue]
}
export default useLocalStorage