PassFront
  1. PassFront
  2. База знаний
  3. Хуки

Какие проблемы решает useCallback?

Хуки

useCallback решает одну проблему: функции, создаваемые в рендере, каждый раз новые по ссылке, и это ломает оптимизации, завязанные на сравнение ссылок.

Проблема 1: сломанный React.memo

const Parent = () => {
  const [text, setText] = useState('');

  const handleDelete = (id) => api.delete(id); // новая ссылка каждый рендер

  return (
    <>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <HeavyList onDelete={handleDelete} /> {/* React.memo бесполезен */}
    </>
  );
};

Каждый ввод символа перерендеривает HeavyList: props «изменились», ведь handleDelete — новая функция. С useCallback ссылка стабильна, и React.memo срабатывает:

const handleDelete = useCallback((id) => api.delete(id), []);

Проблема 2: лишние срабатывания эффектов

const loadData = useCallback(() => fetch(`/api/${page}`), [page]);

useEffect(() => { loadData(); }, [loadData]); // перезапуск только при смене page

Без useCallback функция в зависимостях эффекта означала бы перезапуск на каждый рендер.

Проблема 3: стабильные колбэки для кастомных хуков

Кастомные хуки, принимающие функции (обработчики, колбэки подписок), полагаются на стабильность ссылок в своих зависимостях — useCallback это обеспечивает.

Что useCallback НЕ решает

  • Не ускоряет сам вызов функции и не «кеширует» её результат (это useMemo).
  • Бесполезен, если получатель не мемоизирован и не использует функцию в зависимостях.
  • Не спасает от устаревших замыканий — наоборот, требует аккуратных зависимостей.

Коротко для собеседования

useCallback стабилизирует ссылку на функцию между рендерами. Решает три задачи: React.memo-дети не перерендериваются из-за «новых» колбэков, эффекты с функцией в зависимостях не перезапускаются каждый рендер, кастомные хуки получают стабильные колбэки. Без мемоизированного потребителя — не нужен.

Другие вопросы раздела