| |
| |
| |
| |
| |
| |
|
|
| import { useEffect, useState, useCallback } from 'react'; |
|
|
| export default function useLocalStorage<T>( |
| key: string, |
| defaultValue: T, |
| globalSetState?: (value: T) => void, |
| storageCondition?: (value: T, rawCurrentValue?: string | null) => boolean, |
| ): [T, (value: T) => void] { |
| const [value, setValue] = useState(defaultValue); |
|
|
| useEffect(() => { |
| const item = localStorage.getItem(key); |
|
|
| if (!item && !storageCondition) { |
| localStorage.setItem(key, JSON.stringify(defaultValue)); |
| } else if (!item && storageCondition && storageCondition(defaultValue)) { |
| localStorage.setItem(key, JSON.stringify(defaultValue)); |
| } |
|
|
| const initialValue = item && item !== 'undefined' ? JSON.parse(item) : defaultValue; |
| setValue(initialValue); |
| if (globalSetState) { |
| globalSetState(initialValue); |
| } |
|
|
| function handler(e: StorageEvent) { |
| if (e.key !== key) { |
| return; |
| } |
|
|
| const lsi = localStorage.getItem(key); |
| setValue(JSON.parse(lsi ?? '')); |
| } |
|
|
| window.addEventListener('storage', handler); |
|
|
| return () => { |
| window.removeEventListener('storage', handler); |
| }; |
| |
| }, [key, globalSetState]); |
|
|
| const setValueWrap = useCallback( |
| (value: T) => { |
| try { |
| setValue(value); |
| const storeLocal = () => { |
| localStorage.setItem(key, JSON.stringify(value)); |
| window?.dispatchEvent(new StorageEvent('storage', { key })); |
| }; |
| if (!storageCondition) { |
| storeLocal(); |
| } else if (storageCondition(value, localStorage.getItem(key))) { |
| storeLocal(); |
| } |
| globalSetState?.(value); |
| } catch (e) { |
| console.error(e); |
| } |
| }, |
| [key, globalSetState, storageCondition], |
| ); |
|
|
| return [value, setValueWrap]; |
| } |
|
|