ReactIntermediate5h

Custom hooks.

Extracting reusable behavior. The composition pattern.

What is it?

A custom hook is just a function that calls other hooks. It bundles related state + effects + handlers behind one name so a component can reuse the behavior. useDebounce, useLocalStorage, useMediaQuery, useFetch — all the same pattern: extract logic, return values.

Why it matters

Components without custom hooks become tangled balls of useState + useEffect calls. The same data-fetch logic copied into 12 components is the bug-fix tax that hits month four. A clean custom hook turns that into one import.

What to learn

  • The naming convention: must start with use
  • What to return: tuple, object, or single value (and when each fits)
  • Stable references: when to wrap returned functions in useCallback
  • Testing custom hooks with @testing-library/react renderHook
  • The "controlled" pattern: hooks that accept config and return state
  • When a custom hook is the wrong abstraction — sometimes a regular function is enough

Common pitfall

Over-extracting. A hook used in exactly one component is rarely worth the indirection. Build the logic in the component first; extract when you need it twice. Premature hooks are harder to read than the inline code they replaced.

Resources

Primary (free):

Practice

Write useLocalStorage(key, initialValue). It should read from localStorage on mount, return a [value, setValue] tuple, and write back on every change. Use it in two different components. Done when both components share state across page reloads with no extra code.

Outcomes

  • Extract a reusable hook from inline component logic.
  • Pick the right return shape (tuple, object, single value) for any hook.
  • Write a hook that handles both client + SSR safely.
  • Recognize when a regular function would beat a custom hook.
Back to Frontend roadmap