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.