Lesson 23 of 28Article16 min
Custom Hooks
A custom hook is a function that calls other hooks. Name it useSomething. It lets you share stateful logic between components without copy-paste.
Custom Hooks — extract reusable logic
A custom hook is a function that calls other hooks. Name it useSomething. It lets you share stateful logic between components without copy-paste.
Real-life example: Custom hooks are family recipes — write once, any kitchen (component) can follow the same steps.
useFetch custom hook
import { useState, useEffect } from "react";
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let cancelled = false;
setLoading(true);
fetch(url)
.then((r) => r.json())
.then((d) => { if (!cancelled) setData(d); })
.catch((e) => { if (!cancelled) setError(e.message); })
.finally(() => { if (!cancelled) setLoading(false); });
return () => { cancelled = true; };
}, [url]);
return { data, loading, error };
}
function Courses() {
const { data, loading, error } = useFetch("/api/courses");
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return <ul>{data.map((c) => <li key={c.id}>{c.title}</li>)}</ul>;
}More custom hook ideas
useLocalStorage, useDebounce, useWindowSize, useAuth — all follow the same pattern: hooks inside, return values and functions.
Real-life example: useLocalStorage is a pocket notebook that syncs with a locker (browser storage) — open any component, same notes appear.
Custom hooks return data and functions — not JSX. Keep UI in components.
useLocalStorage sketch
function useLocalStorage(key, initial) {
const [value, setValue] = useState(() => {
const saved = localStorage.getItem(key);
return saved ? JSON.parse(saved) : initial;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}