Какой хук в React соответствует поведению componentDidMount и componentWillUnmount
Что проверяют
Понимаете ли вы, что useEffect это не перенос методов жизненного цикла один в один, а синхронизация компонента с внешним миром. Следом почти всегда спрашивают, почему эффект в разработке срабатывает дважды и когда вызывается функция очистки.
Как отвечать
Базовый ответ: useEffect с пустым массивом зависимостей и функцией очистки.
useEffect(() => {
const id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []);Тело эффекта выполняется после первого рендера, возвращённая функция при размонтировании. Дальше покажите нюансы:
- момент запуска:
useEffectобычно срабатывает после отрисовки кадра, аcomponentDidMountвыполнялся до неё. Если нужно измерить DOM и поправить разметку без мигания, беритеuseLayoutEffect; - очистка: вызывается не только при размонтировании, но и перед каждым повторным запуском эффекта при смене зависимостей. Поэтому одна пара «эффект и очистка» заменяет сразу
componentDidMount,componentDidUpdateиcomponentWillUnmount; - Strict Mode: с React 18 в режиме разработки компонент монтируется, размонтируется и монтируется снова, чтобы проверить очистку. Двойной вызов в dev это не баг, в продакшене его нет;
- зависимости: пустой массив при использовании пропсов и состояния внутри даёт устаревшие замыкания. В React 19.2 появился
useEffectEvent, который читает свежие значения без добавления их в зависимости.
Для загрузки данных в эффекте нужна отмена через AbortController в очистке, иначе ответ старого запроса перезапишет новый. В реальных проектах загрузку чаще отдают TanStack Query или механизмам фреймворка, а эффекты оставляют для подписок, таймеров и сторонних виджетов.
Где спотыкаются
Считают, что очистка вызывается только при размонтировании. Отсюда утечки подписок при смене пропсов.
Видят двойной запуск в dev и убирают StrictMode вместо того, чтобы написать нормальную очистку.
Отключают правило react-hooks/exhaustive-deps, чтобы оставить [], и получают эффект, который работает с данными первого рендера.