← Назад к вопросам

Как реализовать 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;
  };
}, []);
Как реализовать unmount через useEffect? | PrepBro