🌸 Budding Mar 5, 2026

Custom React Hooks

Custom hooks are JavaScript functions that reuse stateful logic across components. They're regular functions that can call other hooks. By convention, they start with 'use'.

useLocalStorage - Persist State:


function useLocalStorage(key, initialValue) {
const [stored, setStored] = useState(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});

const setValue = (value) => {
try {
const valueToStore = value instanceof Function ? value(stored) : value;
setStored(valueToStore);
localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};

return [stored, setValue];
}

useWindowWidth - Responsive:


function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);

useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);

return width;
}

useToggle - Boolean State:

function useToggle(initial = false) {
const [value, setValue] = useState(initial);
const toggle = useCallback(() => setValue(v => !v), []);
return [value, toggle];
}

Composition Pattern:


function useUser(userId) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
let mounted = true;
setLoading(true);

fetchUser(userId)
.then(user => {
if (mounted) {
setUser(user);
setError(null);
}
})
.catch(err => {
if (mounted) setError(err);
})
.finally(() => {
if (mounted) setLoading(false);
});

return () => { mounted = false; };
}, [userId]);

return { user, loading, error };
}

Custom hooks are the ultimate abstraction in React — they encapsulate complexity and share logic without changing the component hierarchy.