aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/hooks')
-rw-r--r--src/utils/hooks/use-local-storage.tsx33
-rw-r--r--src/utils/hooks/use-local-storage/index.ts1
-rw-r--r--src/utils/hooks/use-local-storage/use-local-storage.test.ts59
-rw-r--r--src/utils/hooks/use-local-storage/use-local-storage.ts38
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;
+};