Chapter 3 of 4
Hooks Worth Writing
Four small hooks that show up in almost every project.
useToggle
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue((previous) => !previous), []);
return [value, toggle, setValue];
}
const [isOpen, toggleOpen] = useToggle();useLocalStorage
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
try {
const stored = window.localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
} catch {
return initialValue;
}
});
useEffect(() => {
window.localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}useDebouncedValue
function useDebouncedValue(value, delay = 300) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
return debounced;
}
const query = useDebouncedValue(input, 400); // search only when typing pausesuseOnClickOutside
function useOnClickOutside(ref, handler) {
useEffect(() => {
function listener(event) {
if (!ref.current || ref.current.contains(event.target)) return;
handler(event);
}
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
}, [ref, handler]);
}