Вопрос проверяет понимание жизненного цикла компонентов React и необходимости предотвращения утечек памяти при использовании побочных эффектов.
Хук useEffect в React позволяет выполнять побочные эффекты в функциональных компонентах. Часто эти эффекты создают ресурсы, такие как подписки на события, таймеры или соединения с сервером, которые необходимо освободить, когда компонент удаляется из DOM или перед следующим выполнением эффекта, чтобы избежать утечек памяти и неожиданного поведения.
Функция очистки — это функция, которую вы возвращаете из колбэка, переданного в useEffect. React будет вызывать её в двух случаях:
Это гарантирует, что ресурсы, созданные в предыдущем рендере, будут корректно удалены перед созданием новых.
Рассмотрим пример с подпиской на событие и таймером:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [position, setPosition] = useState({ x: 0, y: 0 });
const [count, setCount] = useState(0);
useEffect(() => {
// Эффект 1: Подписка на событие mousemove
const handleMouseMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener('mousemove', handleMouseMove);
// Эффект 2: Запуск интервала
const intervalId = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
// Функция очистки для обоих эффектов
return () => {
window.removeEventListener('mousemove', handleMouseMove);
clearInterval(intervalId);
};
}, []); // Пустой массив зависимостей = эффект выполняется только при монтировании
return (
Позиция мыши: {position.x}, {position.y}
Счётчик: {count}
);
}В этом примере функция очистки удаляет обработчик события и останавливает интервал. Без неё при каждом обновлении компонента создавались бы новые подписки и таймеры, что привело бы к утечке памяти и некорректному поведению (например, счётчик ускорился бы).
Функции очистки необходимы для любых эффектов, которые:
setInterval, setTimeout).AbortController).Для асинхронных операций, таких как fetch-запросы, часто используют AbortController внутри функции очистки, чтобы отменить запрос, если компонент размонтируется до его завершения.
Вывод: Всегда возвращайте функцию очистки из useEffect, если ваш эффект создаёт ресурсы, которые должны быть освобождены. Это ключевая практика для написания надёжных, не подверженных утечкам памяти React-приложений, особенно при работе с внешними API, событиями или таймерами.