📖 Notes
LESSON 10 OF 18
Custom Hooks — Build Your Own
Extracting Logic You'll Reuse
A custom hook is just a regular function that calls other hooks inside it — the moment you copy-paste the same useState/useEffect pattern twice, it's time to extract one.
Custom Hook Rules
Name, Compose, Return
🏷️
Naming
Must start with "use" (useFetch, useLocalStorage).
🔗
Composition
Can call other hooks inside (useState, useEffect, etc.).
📤
Return Value
Returns whatever the component needs — values, setters, or both.
♻️
Why It Matters
Without custom hooks, every fetching component repeats the same loading/error boilerplate.
useFetch & useLocalStorage
JSX// useFetch
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url).then(r => r.json()).then(setData).catch(setError).finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
// useLocalStorage
function useLocalStorage(key, init) {
const [val, setVal] = useState(() => JSON.parse(localStorage.getItem(key)) ?? init);
const set = v => { setVal(v); localStorage.setItem(key, JSON.stringify(v)); };
return [val, set];
}
// Usage
const { data: courses, loading } = useFetch("/api/courses");
const [theme, setTheme] = useLocalStorage("theme", "dark");