PassFront
  1. PassFront
  2. База знаний
  3. Хуки

Как реализовать жизненные циклы компонентов с помощью useEffect?

Хуки

Все три фазы жизненного цикла классового компонента выражаются одним хуком useEffect — разными комбинациями массива зависимостей и cleanup-функции.

componentDidMount → useEffect(fn, [])

useEffect(() => {
  loadInitialData();
}, []); // один раз после монтирования

Пустой массив: эффект выполнится после первого рендера и больше не перезапустится.

componentDidUpdate → useEffect(fn, [deps])

useEffect(() => {
  loadUser(userId); // при монтировании И при смене userId
}, [userId]);

Отличие от классов: не нужно вручную сравнивать prevProps.userId !== this.props.userId — сравнение зависимостей делает React. Если нужен эффект строго после каждого рендера — массив опускается совсем.

componentWillUnmount → cleanup-функция

useEffect(() => {
  const timer = setInterval(tick, 1000);
  return () => clearInterval(timer); // при размонтировании
}, []);

Всё вместе

useEffect(() => {
  const ws = subscribe(channelId, onMessage); // mount + update по channelId
  return () => ws.close();                    // cleanup перед перезапуском и на unmount
}, [channelId]);

Отличия от классовой модели

  • Cleanup вызывается не только при размонтировании, но и перед каждым перезапуском эффекта — модель «синхронизации», а не «этапов жизни».
  • Логика группируется по смыслу (подписка + отписка рядом), а не разнесена по трём методам.
  • Аналога shouldComponentUpdate у useEffect нет — это задача React.memo.
  • Синхронного аналога componentWillMount нет (и он не нужен); для чтения DOM до отрисовки есть useLayoutEffect.

Коротко для собеседования

useEffect(fn, []) = componentDidMount; useEffect(fn, [deps]) = componentDidUpdate по конкретным данным; cleanup-функция = componentWillUnmount (плюс вызывается перед каждым перезапуском). Хуки группируют связанную логику вместе вместо разнесения по методам класса.

Другие вопросы раздела