import { useState, useCallback, useEffect, } from 'react' import { queryParamStorage } from 'features/QueryParamsStorage' import { dateReplacer, readStorageInitialValue, } from './helpers' const defaultValidator = () => true type Args = { defaultValue: T, key: string, /** * функция для валидации полученного значения из стора * если значение не валидно то используется defaultValue. * Если не передан валидатор то полученное значение из стореджа * считается валидным. */ validator?: (value: T) => boolean, } /** * Хук высшего порядка, получает сторедж * и возвращает хук работающий с данным стореджем * Хук считывает значение из стора и использует как начальное значение стейта, * при вызове сеттера обновляется сторедж и реакт стейет */ const createHook = (storage: Storage) => ( ({ defaultValue, key, validator = defaultValidator, }: Args) => { const getInitialState = () => { const storeValue = readStorageInitialValue(storage, key) const isValid = validator(storeValue) return isValid ? storeValue : defaultValue } const [state, setState] = useState(getInitialState) const setStateAndSave = useCallback((value: T) => { storage.setItem(key, JSON.stringify(value, dateReplacer)) setState(value) }, [key]) useEffect(() => { const storeValue = readStorageInitialValue(storage, key) const isValid = validator(storeValue) if (!isValid) { storage.removeItem(key) } }, [key, validator]) return [state, setStateAndSave] as const } ) export const useLocalStore = createHook(localStorage) export const useSessionStore = createHook(sessionStorage) export const useQueryParamStore = createHook(queryParamStorage)