Как очистить состояние в useEffect?
Хуки
Вопрос двусмысленный. Обычно имеется в виду очистка ресурсов эффекта (cleanup), реже — «сбросить state при размонтировании/смене данных». Разберём оба.
Очистка ресурсов: cleanup-функция
useEffect(() => {
const id = setInterval(tick, 1000);
const ws = new WebSocket(url);
return () => { // ← «очистка» эффекта
clearInterval(id);
ws.close();
};
}, [url]);Вызывается перед каждым перезапуском эффекта (изменились deps) и при размонтировании. Сюда идут: removeEventListener, unsubscribe, disconnect, abort.
Сброс состояния
Сбрасывать state в cleanup бессмысленно: при размонтировании компонент и его состояние исчезают, а setState на удалённом компоненте — ошибка проектирования.
Если нужно сбросить состояние при смене входных данных:
// ❌ через эффект: лишний рендер и мигание
useEffect(() => { setSelected(null); }, [userId]);
// ✅ через key: React пересоздаст компонент с чистым состоянием
<UserPanel key={userId} userId={userId} />Смена key — рекомендованный способ сброса всего состояния поддерева. Для частичного сброса можно вычислять значение при рендере или хранить «предыдущий props» и корректировать состояние во время рендера (продвинутый приём из документации).
Защита от гонок (частый смысл вопроса)
useEffect(() => {
let cancelled = false;
load(id).then((d) => { if (!cancelled) setData(d); });
return () => { cancelled = true; };
}, [id]);Коротко для собеседования
«Очистка в useEffect» — это возвращаемая cleanup-функция: снять подписки, таймеры, закрыть соединения, отменить запросы; вызывается перед перезапуском эффекта и при размонтировании. Сбрасывать state в cleanup не нужно (он исчезает вместе с компонентом); для сброса при смене данных использовать key, а не эффект.