hooks.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { useState, useEffect, useCallback } from 'react';
  2. /**
  3. * Custom hook for persisting form state to localStorage
  4. * @param key - Unique key for localStorage
  5. * @param initialValue - Initial value for the state
  6. * @returns [state, setState, clearState] tuple
  7. */
  8. export function useLocalStorage<T>(
  9. key: string,
  10. initialValue: T
  11. ): [T, (value: T | ((prevValue: T) => T)) => void, () => void] {
  12. // State to store our value
  13. // Pass initial state function to useState so logic is only executed once
  14. const [storedValue, setStoredValue] = useState<T>(() => {
  15. if (typeof window === 'undefined') {
  16. return initialValue;
  17. }
  18. try {
  19. // Get from local storage by key
  20. const item = window.localStorage.getItem(key);
  21. // Parse stored json or if none return initialValue
  22. return item ? JSON.parse(item) : initialValue;
  23. } catch (error) {
  24. // If error also return initialValue
  25. console.warn(`Error loading localStorage key "${key}":`, error);
  26. return initialValue;
  27. }
  28. });
  29. // Return a wrapped version of useState's setter function that ...
  30. // ... persists the new value to localStorage.
  31. const setValue = useCallback(
  32. (value: T | ((prevValue: T) => T)) => {
  33. try {
  34. // Allow value to be a function so we have same API as useState
  35. const valueToStore =
  36. value instanceof Function ? value(storedValue) : value;
  37. // Save state
  38. setStoredValue(valueToStore);
  39. // Save to local storage
  40. if (typeof window !== 'undefined') {
  41. window.localStorage.setItem(key, JSON.stringify(valueToStore));
  42. }
  43. } catch (error) {
  44. // A more advanced implementation would handle the error case
  45. console.error(`Error saving localStorage key "${key}":`, error);
  46. }
  47. },
  48. [key, storedValue]
  49. );
  50. // Function to clear the stored value
  51. const clearValue = useCallback(() => {
  52. try {
  53. setStoredValue(initialValue);
  54. if (typeof window !== 'undefined') {
  55. window.localStorage.removeItem(key);
  56. }
  57. } catch (error) {
  58. console.error(`Error clearing localStorage key "${key}":`, error);
  59. }
  60. }, [key, initialValue]);
  61. return [storedValue, setValue, clearValue];
  62. }
  63. /**
  64. * Hook for auto-saving form state with debouncing
  65. * @param key - Unique key for localStorage
  66. * @param value - Current form value
  67. * @param delay - Debounce delay in milliseconds (default: 500ms)
  68. */
  69. export function useAutoSave<T>(key: string, value: T, delay = 500) {
  70. useEffect(() => {
  71. const timeoutId = setTimeout(() => {
  72. if (typeof window !== 'undefined') {
  73. try {
  74. window.localStorage.setItem(key, JSON.stringify(value));
  75. } catch (error) {
  76. console.error(`Error auto-saving localStorage key "${key}":`, error);
  77. }
  78. }
  79. }, delay);
  80. return () => clearTimeout(timeoutId);
  81. }, [key, value, delay]);
  82. }