function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
try {
const stored = localStorage.getItem(key);
return stored
? JSON.parse(stored)
: initialValue;
} catch {
return initialValue;
}
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
// Usage:
const [theme, setTheme] =
useLocalStorage('theme', 'dark');
function useDebounce(value, delay = 300) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(
() => setDebounced(value), delay
);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
// Usage: slider moves → debounced value
// updates 300ms after you stop
function useKeyboardShortcuts(shortcuts) {
useEffect(() => {
const handler = (e) => {
for (const [combo, action]
of Object.entries(shortcuts)) {
if (matchesCombo(e, combo)) {
e.preventDefault();
action();
}
}
};
window.addEventListener('keydown', handler);
return () => window.removeEventListener(
'keydown', handler
);
}, [shortcuts]);
}
Replace duplicated patterns across 5+ components:
| Before | After | Saved |
|---|---|---|
| localStorage in 5 components | useLocalStorage | ~80 lines |
| Debounce in 4 components | useDebounce | ~60 lines |
| Keyboard in 3 components | useKeyboardShortcuts | ~45 lines |
git switch -c refactor/PIXELCRAFT-032-custom-hooks
git add src/hooks/ src/components/
git commit -m "Extract useLocalStorage, useDebounce, useKeyboardShortcuts (PIXELCRAFT-032)"
git push origin refactor/PIXELCRAFT-032-custom-hooks
# PR → Review → Merge → Close ticket ✅
Abstraction layers.
Each custom hook hides complexity behind a simple interface. The ability to identify the right level of abstraction is what separates good engineers from great ones.