Установка и очистка setTimeout () внутри обработчика событий

У меня есть функция обработчика событий, которая при каждом запуске должна очищать setTimeout() и установите новый тайм-аут.

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

Вот и все. Я сделал это, но считаю, что мое решение не оптимальное и не самое чистое:


let timer;

const handler = (event, type) => {

    clearTimeout(timer);

    if(type === 'CHANGE') timer = setTimeout(callback, 500, { argumentsForTheCallBack });
}

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

Есть ли способ сделать обработчик автономным?

Меня интересуют решения ECMAScript, а также решения с использованием синтаксиса React.js (в моем исходном коде обратный вызов является диспетчером для useReducer крюк)

 

1 ответ
1

Поскольку вы упоминаете useReducer Хук React Я предполагаю, что вы используете функциональный компонент и, следовательно, можете использовать другие хуки React.

Я предлагаю:

  1. Используйте React ref для хранения ссылки на таймер (а не на глобальную переменную).
  2. Используйте useEffect крючок для очистки любых тайм-аутов выполнения в случае, если компонент отключится до истечения тайм-аута. Предоставьте пустой массив зависимостей, чтобы обратный вызов эффекта вызывал только один раз. Здесь просто нужно вернуть функцию очистки, чтобы очистить все тайм-ауты.

Код:

import { useEffect, useRef } from 'react';

...

// in component
const timerRef = useRef(null);

useEffect(() => {
  return () => clearTimeout(timerRef.current);
}, []);

const handler = (event, type) => {
  clearTimeout(timerRef.current);

  if (type === 'CHANGE') {
    timerRef.current = setTimeout(callback, 500, { argumentsForTheCallBack });
  }
}

Зачем нужна функция очистки от useEffect?

Если вы попытаетесь обновить состояние отключенного компонента, вы получите предупреждение React, в котором говорится:

Предупреждение: невозможно выполнить обновление состояния React для отключенного компонента. Это не работает, но указывает на утечку памяти в вашем приложении. Чтобы исправить это, отмените все подписки и асинхронные задачи в функции очистки useEffect.

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

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

 

  • Спасибо за ответ. Я новичок в React и, насколько мне известно, useEffect с пустым массивом, поскольку зависимость должна запускаться только один раз при запуске приложения. Что мне не хватает?

    — Шейх Йербути

  • @SheikYerbouti Да, это именно то намерение. Я обновил ответ, чтобы предоставить эту дополнительную информацию для ясности и цели.

    — Дрю Риз

  • @SheikYerbouti Добавил ответ на ваш последующий вопрос в обновлении моего ответа.

    — Дрю Риз

  • Большое спасибо за объяснение. Теперь я понял, что должен очистить любую асинхронную задачу, но не useEffect выполняется только один раз в начале? Он автоматически вызывается снова, когда компонент отключается? И если да, то только ли это для useEffects с пустым массивом в качестве зависимости?

    — Шейх Йербути

  • @SheikYerbouti В этом случае да, useEffect hook вызывается в конце начального рендеринга, а очистка эффекта будет вызвана при размонтировании компонента. Как правило, функция очистки вызывается в конце цикла визуализации перед повторной визуализацией компонента (для очистки любых эффектов от предыдущей визуализации) или при размонтировании компонента. Эффект с пустой зависимостью и возвращенной функцией очистки примерно эквивалентен componentDidMount а также componentWillUnmount методы жизненного цикла. Видеть reactjs.org/docs/hooks-reference.html#cleaning-up-an-effect.

    — Дрю Риз

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

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