βοΈ
EPISODE 05
Extracting logic Β· naming rules Β· composition
Custom Hooks
Move repeated stateful logic into reusable hook functions. Learn the naming rules, common patterns (useToggle, useFetch, useLocalStorage), and composition.
custom hooksreuseuseLocalStorageuseFetch
Duration
β± About 2 hours
Level
π Intermediate
Prerequisite
π― react-02
OUTCOME
Build at least three reusable hooks used across components
What you'll learn
- 1Name custom hooks with the use prefix
- 2Return a tuple or object from a hook
- 3Compose hooks within hooks
- 4Write a useLocalStorage and useFetch
1. useToggle
tsx
function useToggle(initial = false): [boolean, () => void] {
const [on, setOn] = useState(initial);
const toggle = useCallback(() => setOn(v => !v), []);
return [on, toggle];
}
// Use
const [isOpen, toggleOpen] = useToggle(false);2. useLocalStorage
tsx
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
try {
const raw = localStorage.getItem(key);
return raw !== null ? JSON.parse(raw) as T : initial;
} catch { return initial; }
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}3. useFetch (Simple Version)
tsx
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [error, setError] = useState<Error | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
setLoading(true); setError(null);
fetch(url)
.then(r => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.json(); })
.then(d => { if (!cancelled) setData(d as T); })
.catch(e => { if (!cancelled) setError(e); })
.finally(() => { if (!cancelled) setLoading(false); });
return () => { cancelled = true; };
}, [url]);
return { data, error, loading };
}π‘
For production apps, prefer TanStack Query or SWR β they handle caching, retries, and revalidation for you.
4. Naming Rules
- Must start with "use" β that's how React detects a hook
- Hooks can only call other hooks at the top level (no conditional calls)
- Hooks can only be called from React function components or other hooks
Example code / lecture materials
All lecture materials and example code are openly available on GitHub.
View on GitHub β