MediumHooks📖 Theory Question

What are custom hooks and what are the patterns for building them?

💡

Hint

Functions starting with "use" that call other hooks — extract reusable stateful logic

Full Answer

Custom hooks extract stateful logic from components into reusable functions. They must start with use.

// Custom hook — useFetch
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); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; }; // cleanup race condition
  }, [url]);

  return { data, loading, error };
}

// Usage — clean component
function UserProfile({ id }) {
  const { data: user, loading } = useFetch(`/api/users/${id}`);
  if (loading) return ;
  return 

{user.name}

; }

Common custom hook patterns:

  • useLocalStorage(key, initial) — sync state with localStorage
  • useDebounce(value, delay) — debounce a value
  • useOnClickOutside(ref, handler) — close dropdowns
  • usePrevious(value) — track previous render's value
  • useIntersectionObserver(ref) — lazy loading / infinite scroll
💡 Custom hooks don't share STATE — they share LOGIC. Each component that calls a custom hook gets its own isolated state. Think of them as reusable useState + useEffect combos.

Practice this in a timed sprint →

5 free questions, no signup required

⚡ Start Sprint