~/hackweb.dev
Custom Hooks
Quiz
...

Custom Hooks

intermediate · updated Tue Sep 08 2026Contribute

Extract reusable logic into custom hooks.

Custom Hooks

Custom hooks let you extract component logic into reusable functions.

Naming Convention

Custom hooks must start with use:

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  const increment = () => setCount((c) => c + 1);
  const decrement = () => setCount((c) => c - 1);
  return { count, increment, decrement };
}

Using a Custom Hook

function Counter() {
  const { count, increment, decrement } = useCounter(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={decrement}>-</button>
      <button onClick={increment}>+</button>
    </div>
  );
}

Each component gets its own state.

Example: useLocalStorage

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}

Example: useFetch

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((json) => {
        setData(json);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

Rules of Hooks

  1. Only call hooks at the top level
  2. Only call hooks from React functions or custom hooks
  3. Prefix custom hooks with use

Best Practices

  1. One hook per piece of logic
  2. Keep hooks small and focused
  3. Return arrays for multiple values, objects for named values
  4. Test custom hooks with renderHook

Common Mistakes

  1. Calling hooks inside conditions or loops
  2. Not including all dependencies in effects
  3. Naming without use prefix breaks linting rules