Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 102x 55x 55x 55x 55x 3x 3x 102x 29x 29x 29x 29x 29x 29x 102x 55x 55x 3x 2x 2x 1x 55x 55x 55x 102x | import { useState, useEffect, useCallback } from 'react';
/**
* Custom hook to sync state with localStorage
*
* ## Business Perspective
*
* Enables widgets to remember user preferences and settings across browser
* sessions, improving user experience by maintaining personalized configurations.
* This is particularly valuable for security officers who configure specific
* security levels and want their settings persisted. 💾
*
* ## Technical Perspective
*
* Provides a React state hook that automatically syncs with localStorage,
* handling JSON serialization/deserialization and SSR compatibility. Uses
* the same API as useState for familiarity.
*
* @template T - Type of the stored value
* @param key - localStorage key to use for storage
* @param initialValue - Initial value if key doesn't exist in localStorage
* @returns Tuple of [storedValue, setValue] similar to useState
*
* @example
* ```tsx
* // Store user's preferred theme
* const [theme, setTheme] = useLocalStorage('theme', 'light');
*
* return (
* <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
* Toggle Theme
* </button>
* );
* ```
*
* @example
* ```tsx
* // Store security level preferences
* const [savedLevels, setSavedLevels] = useLocalStorage('securityLevels', {
* availability: 'Moderate',
* integrity: 'Moderate',
* confidentiality: 'Moderate'
* });
* ```
*
* @example
* ```tsx
* // Store widget visibility preferences
* const [widgetPrefs, setWidgetPrefs] = useLocalStorage('widgetPreferences', {
* showDetails: true,
* expandedSections: ['overview', 'metrics']
* });
* ```
*/
export function useLocalStorage<T>(
key: string,
initialValue: T
): [T, (value: T | ((prev: T) => T)) => void] {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState<T>(() => {
// SSR safety: return initial value if window is undefined
Iif (typeof window === 'undefined') {
return initialValue;
}
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
// Parse stored json or return initialValue if none exists
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error reading from localStorage, log and return initial value
console.warn(`Error reading localStorage key "${key}":`, error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that
// persists the new value to localStorage
const setValue = useCallback((value: T | ((prev: T) => T)) => {
try {
// Allow value to be a function like useState
setStoredValue((prevValue) => {
const valueToStore = value instanceof Function ? value(prevValue) : value;
// Save to local storage
Eif (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
return valueToStore;
});
} catch (error) {
// If error writing to localStorage, log but don't throw
console.error(`Error saving to localStorage key "${key}":`, error);
}
}, [key]);
// Sync with changes to localStorage from other tabs/windows
useEffect(() => {
Iif (typeof window === 'undefined') {
return;
}
const handleStorageChange = (e: StorageEvent): void => {
if (e.key === key && e.newValue !== null) {
try {
setStoredValue(JSON.parse(e.newValue));
} catch (error) {
console.warn(`Error parsing storage event for key "${key}":`, error);
}
}
};
// Listen for changes in other tabs/windows
window.addEventListener('storage', handleStorageChange);
return () => {
window.removeEventListener('storage', handleStorageChange);
};
}, [key]);
return [storedValue, setValue];
}
|