Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Очистка эффекта

Некоторые эффекты оставляют после себя что-то работающее: таймер, обработчик события окна, подписку. Если компонент исчезнет со страницы, а таймер продолжит тикать, получится утечка — код работает впустую и может менять состояние несуществующего компонента. Чтобы этого не было, эффект возвращает функцию очистки.

Таймер с очисткой

Создайте src/components/Clock.jsx — часы, которые обновляются каждую секунду:

// src/components/Clock.jsx
import { useEffect, useState } from 'react';
 
export default function Clock() {
  const [time, setTime] = useState(new Date());
 
  useEffect(() => {
    const timer = setInterval(() => setTime(new Date()), 1000);
 
    return () => clearInterval(timer);
  }, []);
 
  return <p>Сейчас {time.toLocaleTimeString()}</p>;
}

Выведите <Clock /> в App — время на странице будет меняться каждую секунду. Функция, которую вернул эффект, останавливает таймер.

Когда React вызывает очистку

МоментЧто происходит
Компонент исчезает со страницыВызывается очистка
Зависимость измениласьСначала очистка старого эффекта, потом запуск нового
Разработка со StrictModeЗапуск, очистка и снова запуск сразу после появления

Проверка на странице

Добавьте в App кнопку, которая показывает и прячет часы:

// src/App.jsx
import { useState } from 'react';
import Clock from './components/Clock.jsx';
 
export default function App() {
  const [showClock, setShowClock] = useState(true);
 
  return (
    <>
      <button onClick={() => setShowClock(!showClock)}>Часы</button>
      {showClock && <Clock />}
    </>
  );
}

Когда часы спрятаны, компонента Clock нет на странице, и его таймер остановлен. Без очистки таймер продолжил бы работать, а в консоли могли бы появиться ошибки.

Обработчик события окна

Так же снимают обработчики, добавленные через addEventListener. Компонент показывает ширину окна — src/components/WindowWidth.jsx:

// src/components/WindowWidth.jsx
import { useEffect, useState } from 'react';
 
export default function WindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
 
  useEffect(() => {
    function handleResize() {
      setWidth(window.innerWidth);
    }
 
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
 
  return <p>Ширина окна: {width}px</p>;
}

Меняйте размер окна браузера — число на странице будет обновляться. В removeEventListener передают ту же функцию, что и в addEventListener.

Что нужно очищать

Что запускает эффектЧем очищать
setInterval, setTimeoutclearInterval, clearTimeout
addEventListenerremoveEventListener
Подписка на внешний источникОтписка, которую он предоставляет
Запрос fetchФлаг «ответ больше не нужен», см. урок про загрузку данных

Частая ошибка

Без очистки в режиме разработки эффект с setInterval запустится дважды, и счётчик будет расти на 2 в секунду вместо 1:

// Неправильно: таймер никогда не останавливается.
useEffect(() => {
  setInterval(() => setSeconds((value) => value + 1), 1000);
}, []);

Если StrictMode выявил двойную работу, это знак, что эффекту не хватает функции очистки.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.