diff options
Diffstat (limited to 'src/utils/hooks')
| -rw-r--r-- | src/utils/hooks/use-local-storage.tsx | 33 | ||||
| -rw-r--r-- | src/utils/hooks/use-local-storage/index.ts | 1 | ||||
| -rw-r--r-- | src/utils/hooks/use-local-storage/use-local-storage.test.ts | 59 | ||||
| -rw-r--r-- | src/utils/hooks/use-local-storage/use-local-storage.ts | 38 |
4 files changed, 98 insertions, 33 deletions
diff --git a/src/utils/hooks/use-local-storage.tsx b/src/utils/hooks/use-local-storage.tsx deleted file mode 100644 index 0f9fbb6..0000000 --- a/src/utils/hooks/use-local-storage.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { LocalStorage } from '../../services/local-storage'; -import { Dispatch, SetStateAction, useEffect, useState } from 'react'; - -export type UseLocalStorageReturn<T> = { - value: T; - setValue: Dispatch<SetStateAction<T>>; -}; - -/** - * Use the local storage. - * - * @param {string} key - The storage local key. - * @param {T} [fallbackValue] - A fallback value if local storage is empty. - * @returns {UseLocalStorageReturn<T>} An object with value and setValue. - */ -export const useLocalStorage = <T,>( - key: string, - fallbackValue: T -): UseLocalStorageReturn<T> => { - const getInitialValue = () => { - if (typeof window === 'undefined') return fallbackValue; - const storedValue = LocalStorage.get<T>(key); - return storedValue ?? fallbackValue; - }; - - const [value, setValue] = useState<T>(getInitialValue); - - useEffect(() => { - LocalStorage.set(key, value); - }, [key, value]); - - return { value, setValue }; -}; diff --git a/src/utils/hooks/use-local-storage/index.ts b/src/utils/hooks/use-local-storage/index.ts new file mode 100644 index 0000000..87c1953 --- /dev/null +++ b/src/utils/hooks/use-local-storage/index.ts @@ -0,0 +1 @@ +export * from './use-local-storage'; diff --git a/src/utils/hooks/use-local-storage/use-local-storage.test.ts b/src/utils/hooks/use-local-storage/use-local-storage.test.ts new file mode 100644 index 0000000..3b63495 --- /dev/null +++ b/src/utils/hooks/use-local-storage/use-local-storage.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from '@jest/globals'; +import { act, renderHook } from '@testing-library/react'; +import { LocalStorage } from '../../../services/local-storage'; +import { useLocalStorage } from './use-local-storage'; + +const validator = (value: unknown): value is string => + typeof value === 'string'; + +describe('useLocalStorage', () => { + const fallback = 'fuga'; + const key = 'qui'; + + it('should return the fallback value when storage is clear', () => { + LocalStorage.clear(); + + const { result } = renderHook(() => + useLocalStorage(key, fallback, validator) + ); + + expect(result.current[0]).toBe(fallback); + }); + + it('should return the stored value when storage is not clear', () => { + const storedValue = 'unde'; + + LocalStorage.set(key, storedValue); + + const { result } = renderHook(() => + useLocalStorage(key, fallback, validator) + ); + + expect(result.current[0]).toBe(storedValue); + }); + + it('should return the fallback value when the stored value is invalid', () => { + LocalStorage.clear(); + + const storedValue = 42; + + LocalStorage.set(key, storedValue); + + const { result } = renderHook(() => + useLocalStorage(key, fallback, validator) + ); + + expect(result.current[0]).toBe(fallback); + }); + + it('can update the stored value', () => { + const { result } = renderHook(() => + useLocalStorage(key, fallback, validator) + ); + const newValue = 'eveniet'; + + act(() => result.current[1](newValue)); + + expect(result.current[0]).toBe(newValue); + }); +}); diff --git a/src/utils/hooks/use-local-storage/use-local-storage.ts b/src/utils/hooks/use-local-storage/use-local-storage.ts new file mode 100644 index 0000000..47b98ff --- /dev/null +++ b/src/utils/hooks/use-local-storage/use-local-storage.ts @@ -0,0 +1,38 @@ +import { useEffect, useState } from 'react'; +import { LocalStorage } from '../../../services/local-storage'; +import type { Validator } from '../../../types'; + +const getInitialValueOrFallback = <T>( + key: string, + fallbackValue: T, + validator: Validator<T> +) => { + if (typeof window === 'undefined') return fallbackValue; + const storedValue = LocalStorage.get(key); + + return validator(storedValue) ? storedValue : fallbackValue; +}; + +/** + * Use the local storage. + * + * @param {string} key - The storage local key. + * @param {T} fallbackValue - A fallback value if local storage is empty. + * @param {Validator<T>} validator - A function to validate the stored value. + * @returns A tuple with the value and a setter. + */ +export const useLocalStorage = <T>( + key: string, + fallbackValue: T, + validator: Validator<T> +) => { + const [value, setValue] = useState( + getInitialValueOrFallback(key, fallbackValue, validator) + ); + + useEffect(() => { + LocalStorage.set(key, value); + }, [key, value]); + + return [value, setValue] as const; +}; |
