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

Как useCallback помогает оптимизировать дочерние компоненты?

Хуки

useCallback помогает дочерним компонентам одним способом: сохраняет ссылку на функцию-проп между рендерами, благодаря чему мемоизированный ребёнок может пропустить свой ререндер.

Проблема

Функции в теле компонента пересоздаются каждый рендер:

const Dashboard = () => {
  const [tab, setTab] = useState('main');

  const handleRefresh = () => reload();  // НОВАЯ функция каждый рендер

  return (
    <>
      <Tabs value={tab} onChange={setTab} />
      <HeavyTable onRefresh={handleRefresh} />
    </>
  );
};

const HeavyTable = React.memo(Table); // memo НЕ РАБОТАЕТ:
// props «изменились» — onRefresh каждый раз новый по ссылке

Каждое переключение таба перерисовывает тяжёлую таблицу впустую.

Решение

const handleRefresh = useCallback(() => reload(), []);

Теперь ссылка стабильна: React.memo сравнивает props (Object.is), видит «ничего не изменилось» и пропускает рендер таблицы.

Вторая линия эффекта: хуки ребёнка

Даже без memo стабильный колбэк полезен, если ребёнок кладёт его в зависимости:

const Child = ({ onRefresh }) => {
  useEffect(() => {
    const id = setInterval(onRefresh, 60000);
    return () => clearInterval(id);
  }, [onRefresh]); // стабильный onRefresh → интервал не пересоздаётся
};

Обязательные условия

  • React.memo на ребёнке — сам useCallback рендеры не пропускает.
  • Все остальные props тоже стабильны — один инлайн-объект/children рушит сравнение.
  • Честные deps у useCallback, иначе либо нестабильность, либо устаревшее замыкание; state внутри колбэка — через функциональные сеттеры.

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

useCallback даёт дочернему компоненту стабильную ссылку на колбэк: React.memo видит равные props и пропускает ререндер; заодно не перезапускаются эффекты ребёнка с этим колбэком в deps. Работает только в связке: memo на ребёнке + стабильность остальных props + корректные зависимости.

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