diff --git a/src/services/localStorage.ts b/src/services/localStorage.ts new file mode 100644 index 0000000..f253553 --- /dev/null +++ b/src/services/localStorage.ts @@ -0,0 +1,74 @@ +'use client' + +import React, {useEffect, useState} from "react"; + +/** + * A custom React hook that allows you to store and retrieve data in the browser's localStorage. + * + * @param {string} key - The key under which the data should be stored in localStorage. + * @param {T} initial - The initial value for the stored data. + * @returns {[T, React.Dispatch>]} - An array containing the stored value and a function to update the stored value. + */ +export function useLocalStorage(key: string, initial: T): [T, React.Dispatch>] { + const readValue = () => { + const item = typeof window !== 'undefined' ? window.localStorage.getItem(key) : null + + if (item) { + try { + return JSON.parse(item) + } catch(error) { + console.warn(`Error reading localStorage key “${key}”:`, error) + } + } + + return initial + } + + const [storedValue, setStoredValue] = useState(readValue) + + useEffect(() => { + try { + typeof window !== 'undefined' && window.localStorage.setItem(key, JSON.stringify(storedValue)) + } catch (error) { + console.warn(`Error setting localStorage key “${key}”:`, error) + } + }, [key, storedValue]) + + return [storedValue, setStoredValue] +} + +/** + * Custom hook that provides a way to store and retrieve encoded values in local storage. + * + * @template T - The type of the value to be stored. + * + * @param {string} key - The key to be used for storing the encoded value in local storage. + * @param {T} fallbackValue - The fallback value to be used if no value is found in local storage. + * + * @return {readonly [T, React.Dispatch>]} - An array containing the encoded value and a function to update the encoded value. + */ +export function useEncodedLocalStorage(key: string, fallbackValue: T): readonly [T, React.Dispatch>] { + const [encodedValue, setEncodedValue] = useState(() => { + const stored = localStorage.getItem(key); + return stored ? safelyParse(stored, fallbackValue) : fallbackValue; + }); + useEffect(() => { + localStorage.setItem(key, safelyStringify(encodedValue)); + }, [key, encodedValue]); + return [encodedValue, setEncodedValue] as const; + + function safelyParse(stored: string, fallback: T): T { + try { + return JSON.parse(atob(stored)); + } catch { + return fallback; + } + } + function safelyStringify(value: T): string { + try { + return btoa(JSON.stringify(value)); + } catch { + return btoa(JSON.stringify(fallbackValue)); + } + } +} \ No newline at end of file