Когда запускается функция очистки при использовании перехвата useEffect с зависимостями?

#javascript #reactjs #react-hooks

#javascript #reactjs #реагирующие перехваты

Вопрос:

Я использую useEffect, чтобы показать загрузку пользовательского интерфейса… но только через 250 мс. Это работает… но я действительно не понимаю, почему и особенно, как и когда useEffect вызывает возвращаемую функцию (которая очищает время ожидания).

Что ж … Я не уверен, что это работает идеально. Иногда должно появляться сообщение «Загрузка …», но его нет.

  const [loadingAfterShortTime, setLoadingAfterShortTime] = useState(false);

 useEffect(() => {
  setLoadingAfterShortTime(bool => false);
  if (myDepandanceToTrigTheLoadingWord === true) {
    const id = setTimeout(() => {
      setLoadingAfterShortTime(bool => true);
    }, 250);
    return () => {
      clearTimeout(id);
    };
  }
}, [myDepandanceToTrigTheLoadingWord]);
  

Комментарии:

1. Эй, я только что изменил название вашего заголовка, чтобы оно было в форме вопроса. Не стесняйтесь изменять его, если вы считаете, что я не очень хорошо справился с сохранением цели исходного вопроса.

2. Функция очистки вызывается всякий раз, когда изменяются зависимости, и когда компонент размонтирован.

3. Итак … за исключением случая, когда компонент размонтирован, все содержимое, включаемое в функцию useEffect, включая оператор return, вызывается при каждом изменении зависимости?

Ответ №1:

Объяснение, предоставленное @Powell Ye, хорошее, однако в нем содержится немного ошибочной информации, особенно когда речь идет о повторном рендеринге (например, при изменении реквизита)

рассмотрим какой-нибудь простой компонент со следующим

     useEffect( () => {
        console.log('Effect is applied')
        //some logic
        return () => {
            console.log('cleaning up')
            //cleanup logic
        }
    })
    return (<>
        {console.log('rendering...')}
     </>)
  

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

  1. «очистка»
  2. новые реквизиты
  3. ‘рендеринг…’
  4. «Эффект применен»

Однако на самом деле происходит следующее

  1. новые реквизиты
  2. ‘рендеринг…’
  3. «очистка»
  4. «Эффект применен»

То есть функция очистки запускается ПОСЛЕ нового рендеринга / рисования, но ДО применения «новых» эффектов, документы могут быть немного двусмысленными по этому поводу

предыдущий эффект очищается перед выполнением следующего эффекта

Это сделано из соображений производительности => чтобы рендеринг не задерживался (для меня это тоже иногда может расстраивать)

Комментарии:

1. Была ли реальная необходимость в создании другого ответа? Спасибо, что указали на несоответствие, однако ваше поведение кажется несколько грубым, поскольку вы могли бы предложить улучшение моего и без того исчерпывающего объяснения.

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

Ответ №2:

Вот краткое описание задействованных временных интервалов:

  • useEffect вызывается при первоначальном рендеринге и всякий раз, когда какое-либо из значений зависит от изменения. Как правило, она запускается после завершения рендеринга. Если вы думаете об этом в терминах компонента на основе класса, эквивалентным был бы componentDidMount метод.
  • Функция, возвращаемая изнутри useEffect , вызывается перед удалением компонента из пользовательского интерфейса или перед повторным рендерингом (во избежание утечек памяти). Предыдущий эффект всегда очищается перед выполнением следующего эффекта. Она гарантированно запускается перед любыми новыми рендерами. Эквивалентом было бы componentWillUnmount .

Пример

Давайте предположим, что существует useEffect с несколькими зависимостями, созданными из реквизитов (которые передаются нашему компоненту) функция очистки. При первом рендеринге произойдет следующее:

  • Как только компонент смонтирован, будет запущен код внутри тела effect;
  • Функция очистки остается на месте, готовая к запуску до того, как компонент повторно отобразится / будет удален с экрана.

Теперь давайте представим, что что-то запускает повторный рендеринг. Поскольку это указано как нечто, от чего useEffect зависит, эффект будет повторно выполнен следующим образом:

  • Функция очистки выполняется после завершения рендеринга;
  • Сразу после этого будет запущен код внутри тела effect;
  • Создается новая функция очистки, опять же, готовая к выполнению после повторного рендеринга компонента / или до его удаления с экрана.

Комментарии:

1. Если мой компонент не удален (меняются только deps). Систематически ли вызывается функция, возвращаемая изнутри useEffect , при изменении зависимостей? И если да, то когда именно, по сравнению с render ?

2. Я добавил пример к своему ответу, описывающий цикл. Надеюсь, это понятно!

3. 😃Чудесно! Merci beaucoup … Где вы этому научились, пожалуйста?

4. De rien! 🙂 Рад, что смог помочь. Чтобы ответить на ваш вопрос: в основном официальные документы и, конечно, практическая пробная версия.

Ответ №3:

Согласно документации react,

Очистка эффекта

Функция очистки запускается перед удалением компонента из пользовательского интерфейса, чтобы предотвратить утечки памяти. Кроме того, если компонент выполняет рендеринг несколько раз (как они обычно делают), предыдущий эффект очищается перед выполнением следующего эффекта.

Выбор времени эффектов

React всегда удаляет эффекты предыдущего рендеринга перед запуском нового обновления.

Насколько я понимаю из обеих цитат, очистка выполняется после применения эффекта и до того, как компонент размонтирован (удален из пользовательского интерфейса).