← Назад к вопросам
Как реализовать unmount через useEffect?
2.0 Middle🔥 251 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация unmount через useEffect
Функция очистки (cleanup function) в useEffect срабатывает при размонтировании компонента или перед переходом к следующему эффекту. Это критически важно для предотвращения утечек памяти.
Базовый синтаксис cleanup function
import { useEffect } from 'react';
function Component() {
useEffect(() => {
console.log('Компонент смонтирован');
return () => {
console.log('Компонент размонтирован');
};
}, []);
return <div>Hello</div>;
}
Очистка слушателей событий
function WindowResizeListener() {
useEffect(() => {
const handleResize = () => {
console.log('Window resized:', window.innerWidth);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return <div>Resize the window</div>;
}
Отмена асинхронных операций
function DataFetcher({ id }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
try {
const response = await fetch('/api/data/' + id);
const json = await response.json();
if (isMounted) {
setData(json);
}
} catch (error) {
if (isMounted) {
console.error('Fetch error:', error);
}
} finally {
if (isMounted) {
setLoading(false);
}
}
};
fetchData();
return () => {
isMounted = false;
};
}, [id]);
if (loading) return <div>Loading...</div>;
return <div>Data: {JSON.stringify(data)}</div>;
}
Очистка таймеров и интервалов
function Timer() {
useEffect(() => {
const timeoutId = setTimeout(() => {
console.log('Timeout executed');
}, 2000);
return () => clearTimeout(timeoutId);
}, []);
return <div>Timer component</div>;
}
function Stopwatch() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
return () => clearInterval(intervalId);
}, []);
return <div>Seconds: {seconds}</div>;
}
Отписка от WebSocket
function WebSocketComponent() {
useEffect(() => {
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
console.log('Connected to WebSocket');
};
ws.onmessage = (event) => {
console.log('Message received:', event.data);
};
return () => {
console.log('Disconnecting from WebSocket');
ws.close();
};
}, []);
return <div>WebSocket Component</div>;
}
Множественные эффекты с cleanup
function ComplexComponent({ userId }) {
useEffect(() => {
let isMounted = true;
fetch('/api/users/' + userId)
.then(res => res.json())
.then(data => {
if (isMounted) {
console.log('User data loaded');
}
});
return () => {
isMounted = false;
};
}, [userId]);
useEffect(() => {
const listener = () => console.log('Notification received');
document.addEventListener('notification', listener);
return () => {
document.removeEventListener('notification', listener);
};
}, []);
return <div>Complex Component</div>;
}
Общие ошибки
// ОШИБКА 1: Забыли вернуть cleanup функцию
useEffect(() => {
window.addEventListener('scroll', handleScroll);
}, []);
// ПРАВИЛЬНО:
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
// ОШИБКА 2: Установка состояния после размонтирования
useEffect(() => {
let isMounted = true;
setTimeout(() => {
if (isMounted) {
setData(response);
}
}, 1000);
return () => {
isMounted = false;
};
}, []);