Skip to main content

Що робить cleanup-функція в useEffect()?

Вона допомагає уникнути витоків пам'яті, подвійних підписок, зайвих викликів і помилок на кшталт

"Can't perform a React state update on an unmounted component".


Визначення

Cleanup-функція - це функція, яку ти повертаєш з useEffect, і яку React викличе автоматично:

  • перед розмонтуванням компонента
  • або перед наступним запуском цього ефекту (якщо залежності змінилися)

Синтаксис

javascript
useEffect(() => { // Тіло ефекту - виконується при монтуванні або оновленні return () => { // Cleanup - виконується при розмонтуванні або перед новим ефектом }; }, [dependencies]);

Коли саме вона викликається

СценарійКоли викличеться cleanup
Компонент розмонтуєтьсяОдин раз, перед видаленням з DOM
Змінилася залежність ефектуСпочатку cleanup старого ефекту, потім новий запуск
Компонент перерендерився, але залежності не змінилисяCleanup не викликається

Приклад 1 - очищення таймера

javascript
useEffect(() => { const id = setInterval(() => { console.log('tick'); }, 1000); return () => { clearInterval(id); // Очищення при розмонтуванні console.log('очищено'); }; }, []); // [] → ефект спрацює один раз

Що станеться:

  • При монтуванні створюється таймер.
  • При розмонтуванні (видаленні компонента) cleanup зупинить інтервал.

Приклад 2 - відписка від подій

javascript
useEffect(() => { const handleResize = () => console.log(window.innerWidth); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); // очищення }; }, []);

Якщо не зробити cleanup, обробник залишиться активним навіть після видалення компонента - витік пам'яті.


Приклад 3 - при зміні залежностей

javascript
useEffect(() => { console.log('Запуск ефекту для user:', userId); return () => { console.log('Очищення перед новим ефектом user:', userId); }; }, [userId]);

Що станеться:

  • При зміні userId React спочатку викличе cleanup старого ефекту, а потім запустить новий ефект.
  • Це важливо для скасування старих запитів, закриття з'єднань тощо.

Приклад 4 - скасування асинхронних запитів

javascript
useEffect(() => { const controller = new AbortController(); fetch(`/api/user/${userId}`, { signal: controller.signal }) .then(res => res.json()) .then(console.log) .catch(console.error); return () => { controller.abort(); // скасовуємо запит, якщо компонент розмонтується }; }, [userId]);

Якщо користувач швидко перемкне userId, старий запит скасується, і новий ефект почнеться з чистого стану.


Чому cleanup важливий

Без cleanup-функцій можливі:

  • Витоки пам'яті (таймери, підписки, WebSocket, слухачі)

  • Дублювання ефектів при оновленнях

  • Помилки на кшталт:

    "Can't perform a state update on an unmounted component"


Аналогія в класових компонентах

Функціональні компонентиКласові компоненти
return () => {...} всередині useEffect()componentWillUnmount()
useEffect(() => {...}, [deps])componentDidUpdate() + componentWillUnmount() разом

Міні-таблиця поведінки

ДіяВикликається ефектВикликається cleanup
МонтуванняТакНі
Оновлення зі зміною залежностейТакТак (перед цим)
Оновлення без зміни залежностейНіНі
РозмонтуванняНіТак

Підсумок

Cleanup-функція в useEffect() - це механізм очищення побічних ефектів, який React викликає перед видаленням компонента або перед повторним виконанням ефекту.

Вона:

  • звільняє ресурси (таймери, події, сокети),
  • запобігає витокам,
  • гарантує, що компонент завжди працює у "чистому" стані.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.