Как 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 + корректные зависимости.