Хук useEffect

useEffect – это один из хуков (специальных функций), который для функциональных компонент заменяет в совокупности такие методы жизненного цикла классовых компонент, как componentDidMount (вызывается после монтирования компоненты), componentDidUpdate (после ее обновления) и componentWillUnmount (после удаления).  С помощью useEffect, мы можем вызывать разные побочные эффекты после того, как компонент отрендерится. Некоторым из этих эффектов нужен сброс (прописывается return внутри useEffect), поэтому они возвращают соответствующую функцию.

useEffect по умолчанию  выполняется после каждой отрисовки компоненты, но в качестве второго параметра можно указать массив зависимостей, только после изменнеия которых он будет применяться повторно. Если же массив оставлять пустым, то перерисовка произойдет только раз после первой загрузки компоненты.

Применение

1. Импортируем из реакт, как и другие хуки:

import React, { useState, useEffect } from 'react';

2. Допустим, нам нужно использовать useEffect, чтобы уже после гарантированной загрузки компоненты передать в нее данные, избагая ситуации, когда данные с сервера еще не пришли и нужное значение в пропсах пустое:

const ProfileStatusWithHooks = (props) => {

///... здесь "разкукоживаем" наш useState, в котором хранится status ...

useEffect( () => {
    setStatus(props.status) //меняем значение в useState
  })

....

return (...)

Теперь сразу отрендерится компонента, а потом useEffect перерисует ее с полученными данными. В таком виде это будет происходить каждый раз после монтирования компоненты. Но в данном случае нам это не подойдет, так как при попытке изменить статус при введении буквы компонента будет повторно рендериться и сразу же перерисовываться этим хуком. В результате мы не сможем “переперенабрать” текст статуса в инпуте, так как тот будет все время перезагружаться.

3. Выходит, что нам нужно применить useEffect только после первой загрузки компоненты. Сделать это можно, указав вторым параметром пустой массив:

useEffect( () => {
    setStatus(props.status)
  }, [])

В итоге useEffect сработает раз и не будет мешать потом вводить новый статус в нашу redux-форму (в примере ее не показано). Но использовать такой пустой массив в этом случае считается неправильно, мы как-будто здесь обманываем Реакт. Подробнее об этом рассказывает Ден Абрамов в своей статье useEffect. Это как буд-то мы что-то не договариваем Реакту. Нам желательно указать какой-то конкретный параметр вместо пустого массива для подписки на его изменения.

4. Поэтому в таком простом примере нам можно просто указать в качестве подписки наш props.status. Здесь это сработает идеально:

useEffect( () => {
    setStatus(props.status)
  }, [props.status])

Второй пример “из учебника”

Но в более сложных ситуациях, например, когда для подписки будет использовано значение счетчика (count), SetInterval будет при каждом изменении count очищаться и запускаться снова. Вероятно, нас это не устроит. В таком случае, как говорит в статье Д. Абрамов, можно применить такую стратегию, как сделать эффект самодостаточным (т.е. он сам меняет значение, при изменении которого перерисовывается):

  • до применения этой стратегии:
    useEffect(() => {
        const id = setInterval(() => {
          setCount(count + 1);
        }, 1000);
        return () => clearInterval(id);
      }, [count]);

     

  • после применения этой стратегии (делаем эффект самодостаточным)
    useEffect(() => {
      const id = setInterval(() => {
        setCount(c => c + 1);
      }, 1000);
      return () => clearInterval(id);
    }, []);

В итоге у нас теперь не перерисовывается SetInterval постоянно. Посмотреть этот пример в работе можно здесь. Интересно, что кажется в данном случае Д. Абрамов не отзывается плохо об использовании пустого массива в качестве второго параметра.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *