Очистка эффекта
Тема дорожной карты · React
Очистка эффекта в React — это необязательная функция, возвращаемая из коллбэка useEffect, которую React вызывает перед повторным запуском эффекта или при размонтировании компонента. Функции очистки необходимы для предотвращения утечек памяти и устаревшего поведения: они отменяют таймеры setTimeout или setInterval, прерывают запросы fetch с помощью AbortController, отписываются от слушателей событий или разрывают WebSocket-соединения. Без корректной очистки эффектов React-компоненты могут продолжать выполнять побочные эффекты после размонтирования, вызывая предупреждения об обновлении состояния и незаметные баги в одностраничных приложениях. В режиме Strict Mode React (используемом в разработке) эффекты намеренно запускаются дважды для выявления отсутствующих очисток, помогая разработчикам обнаруживать и устранять эти проблемы на раннем этапе. Освоение очистки эффектов с useEffect критически важно для построения надёжных, не допускающих утечек React-приложений.
Как это работает
Очистка эффекта строится на useState для локального состояния компонента и useEffect для сайд-эффектов (мутации DOM, подписки, сеть). useState(initial) возвращает [value, setValue]; вызов setValue(next) планирует ререндер. useEffect(fn, deps) запускает fn после рендера при изменении любого элемента deps; возврат функции из fn регистрирует cleanup. Хуки должны вызываться в одном и том же порядке каждый рендер — никогда внутри if или циклов.
Когда применять
useState — для состояния одного компонента (toggle, поля формы, hover). Поднимайте state к ближайшему общему предку, когда двум компонентам нужно его делить. useEffect — для сайд-эффектов (подписки, синк, фетч), не для производных значений (считайте их inline) или трансформации props (делайте на рендере). Пустой deps=[] запускает один раз на mount; пропущенные deps — эффект на каждый рендер (почти всегда ошибка).
Типичные ошибки
Ловушки Очистка эффекта: stale closures (setCount(count + 1) ловит count этого рендера — используйте setCount(c => c + 1)); пропущенные deps и эффекты на каждый рендер; чрезмерный useEffect для того, что React делает сам (computed values, зеркалирование props); неверный cleanup (подписка осталась = утечка памяти при unmount). Прочтите гайд "You Might Not Need an Effect" — он убирает половину useEffect в реальных кодовых базах.