Справочник React
useEffect: синхронизация компонента с внешним миром
useEffect запускает код после отображения компонента и помогает синхронизироваться с внешними системами: сетью, таймером, DOM API или подпиской.
Рабочий пример
useEffect(() => {
const controller = new AbortController();
loadUser(userId, controller.signal).then(setUser);
return () => controller.abort();
}, [userId]);Массив зависимостей перечисляет значения из компонента, используемые эффектом. Функция очистки выполняется перед повторным запуском и при удалении компонента.
Когда применять
Вычисления из props и state делай прямо во время рендера, а обработку пользовательского действия — в обработчике. Эффект нужен для внешней синхронизации, а не для любой последовательности кода.
Проверь пример самостоятельно: измени исходные данные, убери одну строку и сравни результат. Такой короткий эксперимент помогает увидеть роль каждого свойства или метода и не превращает обучение в механическое копирование.
Частые ошибки
- Игнорировать предупреждение о зависимостях
- Обновлять state в эффекте без необходимости
- Не отменять подписку или запрос
Эффект — это синхронизация с внешним миром
Заголовок вкладки, подписка на событие окна, запрос к серверу и таймер живут вне обычного рендера. Их место в useEffect. Вычислить чётность счётчика или отфильтровать массив эффектом не нужно: это обычный код в теле компонента.
Эффект запускается после того, как React отрисовал компонент. Массив зависимостей говорит, когда запускать его снова. Пустой массив — после появления. Массив с query — ещё и когда запрос поиска изменился.
useEffect(() => {
const controller = new AbortController();
async function load() {
const response = await fetch(`/api/lessons?q=${query}`, {
signal: controller.signal
});
if (response.ok) setLessons(await response.json());
}
load();
return () => controller.abort();
}, [query]);Функция очистки отменяет прошлый запрос. Без неё медленный ответ на старую букву может приехать позже и затереть актуальный список.
Зависимости не обманывают
Если внутри эффекта читается query, он должен быть в массиве. Пустой массив при changing query оставит старое замыкание, и запрос будет уходить с первой строкой навсегда. Отключать предупреждение линтера здесь вредно.
Не ставь в зависимости значение, которое сам эффект же и меняет без нужды. Получится цикл запросов. Если state нужен только чтобы записать результат, в зависимости его нет.
Когда эффекта быть не должно
- Реакция на клик — в обработчике
onClick, а не в эффекте, который смотрит на флаг. - Производные данные считай в рендере.
- Сброс state при смене
idиногда проще сделать черезkeyу компонента. - Эффект без очистки, который вешает глобальный слушатель, накопит обработчики при каждом заходе.
Задание
Загружай профиль при смене userId и отменяй предыдущий запрос при быстром переключении.
Проверка: результат должен работать с клавиатуры, не создавать ошибок в консоли и оставаться понятным без пояснений автора.
Практикум по теме
- Ошибка запроса в состоянии компонента — Загрузка, успех и ошибка — три состояния, и одно из них не должно затирать остальные.