Для чего нужен callback в useEffect?
Хуки
Callback (первый аргумент useEffect) — это сама функция эффекта: код, который React выполнит после коммита рендера. Именно в нём живёт вся работа с внешним миром.
Что делает callback
useEffect(() => {
// тело колбэка — побочный эффект
const socket = connect(roomId);
setOnline(true);
// возвращаемая функция — cleanup
return () => socket.disconnect();
}, [roomId]);- Выполняется после того, как изменения попали в DOM (и после отрисовки кадра), поэтому в нём безопасно читать DOM, делать запросы, ставить подписки.
- Может вернуть cleanup-функцию — React вызовет её перед следующим запуском эффекта и при размонтировании.
Почему эффекты нельзя выполнять прямо в теле компонента
Тело компонента — рендер, он должен быть чистым: React может вызывать его многократно (StrictMode, конкурентный рендеринг) и в любой момент. Запрос или подписка в теле выполнялись бы на каждый рендер и дублировались. Callback в useEffect выполняется контролируемо: после коммита и только когда изменились зависимости.
Требования к колбэку
- Должен возвращать функцию или undefined, поэтому нельзя передавать async-функцию (она возвращает Promise). Асинхронность оформляется внутри:
useEffect(() => {
let cancelled = false;
(async () => {
const data = await fetchData(id);
if (!cancelled) setData(data);
})();
return () => { cancelled = true; };
}, [id]);- Значения, которые колбэк использует, должны быть в массиве зависимостей, иначе он «замкнёт» устаревшие данные.
Коротко для собеседования
Callback в useEffect — функция самого эффекта: выполняется после коммита рендера, содержит побочную логику (запросы, подписки, работа с DOM) и может вернуть cleanup. Выносить эффекты в колбэк нужно потому, что рендер обязан оставаться чистым; async напрямую нельзя — колбэк должен вернуть функцию очистки, а не Promise.