Как использовать useEffect помимо запросов на сервер?
Хуки
useEffect — не «хук для запросов», а механизм синхронизации с внешним миром. Запросы — лишь один из случаев (и, кстати, тот, где эффект стоит заменить на React Query).
Подписки на события
useEffect(() => {
const onKey = (e) => e.key === 'Escape' && close();
document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
}, [close]);Сюда же: resize/scroll, matchMedia (тема, брейкпоинты), online/offline, visibilitychange.
Соединения и потоки
WebSocket, EventSource, WebRTC: подключение при монтировании/смене канала, закрытие в cleanup.
Таймеры
setInterval для тикающих часов и поллинга, setTimeout для автосейва и дебаунса — с обязательной очисткой.
Синхронизация с браузером и внешними системами
document.title, meta-теги;- localStorage/sessionStorage (сохранение черновика при изменении state);
- аналитика: pageview при смене маршрута, отправка событий;
- IntersectionObserver/ResizeObserver — ленивая подгрузка, измерения (часто в кастомных хуках).
Интеграция с не-React библиотеками
Инициализация карты, чарта, редактора в контейнер по ref и уничтожение в cleanup — классический «мост» между React и императивным API.
Императивная работа с DOM
Фокус, скролл к элементу, воспроизведение медиа. Если результат виден глазу и может «мигнуть» (позиционирование) — useLayoutEffect.
Где эффект НЕ нужен
Производные данные (useMemo/вычисление в рендере), реакция на клик (обработчик), серверные данные (React Query), сброс состояния при смене props (key).
Коротко для собеседования
useEffect — для синхронизации с внешними системами: подписки на события, WebSocket/таймеры, работа с localStorage и title, аналитика, обсерверы, инициализация не-React библиотек, императивный DOM (фокус, скролл). Не нужен для вычислений, обработки событий и загрузки данных, если есть React Query.