Сброс функции setTimeout для предотвращения действия

#javascript #css #reactjs #timeout #settimeout

#javascript #css #reactjs #тайм-аут #settimeout

Вопрос:

Возможно, я думаю об этом неправильно. Поэтому любые рекомендации были бы очень полезны.

У меня есть элемент, затем при нажатии открывается несколько переключателей. Нажатие одной из переключателей запускает setTimeout 2300ms это, добавит класс Frequency--closing к элементу Frequency , который запускает анимацию в css, по истечении времени ожидания этот компонент удаляется из DOM.

Я использую тайм-аут как средство разрешения анимации до того, как она будет удалена из DOM.

То, к чему я стремлюсь, — это когда я нажимаю переключатель, а затем нажимаю другой переключатель, прежде чем компонент будет удален из DOM, который сбрасывает таймер, поэтому при 2-м щелчке он ожидает другого 2300ms , прежде чем он будет удален из DOM.

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

 const SavedSearchBox = ({ modifier, search, loading }) => {
  const [frequencyToggled, setFrequencyToggled] = useState(false);
  const [closeFrequency, setCloseFrequency] = useState(false);
  const timeoutRef = useRef(null);

  const onToggle = () => {
    if (frequencyToggled) {
      setCloseFrequency(true);
      timeoutRef.current = setTimeout(
        () => setFrequencyToggled(!frequencyToggled),
        2300
      );
    } else {
      setCloseFrequency(false);
      setFrequencyToggled(!frequencyToggled);
      clearTimeout(timeoutRef.current);
    }
  };

  useEffect(() => () => clearTimeout(timeoutRef.current), []);

  return (
    <div
      className={`SavedSearchBox ${modifier ? modifier : ""} ${
        loading amp;amp; loading.status ? "SavedSearchBox--loading" : ""
      }`}
    >
      <div className="SavedSearchBox-footer">
        {frequencyToggled ? (
          <Frequency
            closeFrequency={closeFrequency}
            onChange={() => onToggle()}
          />
        ) : (
          <div onClick={() => onToggle()}>Click Here</div>
        )}
      </div>
    </div>
  );
};
 

onToggle() Функция также вызывается из дочернего компонента Frequency . Этот компонент также включает класс Frequency--closing для анимации закрытия.

 const Frequency = props => {
  const [active, setActive] = useState(0);

  const inputs = [
    ["Instant Alerts", "Instant"],
    ["Twice Daily Alerts", "Twice"],
    ["Daily Alerts", "Daily"],
    ["Weekly Alerts", "Weekly"],
    ["No Email Alerts", "None"]
  ];
  return (
    <div
      className={`Frequency ${
        props.closeFrequency ? "Frequency--closing" : ""
      }`}
    >
      <div className="Frequency-list">
        {inputs.map(([text, value], i) => (
          <div key={i} className="Frequency-listItem">
            <label className="Frequency-listLabel">
              {text}
              <input
                type="radio"
                checked={value === inputs[active][1]}
                onChange={() => {
                  props.onChange();
                  setActive(i);
                }}
                value={value}
              />
              <span className="Frequency-listRadio" />
            </label>
          </div>
        ))}
      </div>
    </div>
  );
};
 

Вот анимации в случае, если это, возможно, вызывает эту проблему

 .Frequency-listItem {
  animation: enter $Frequency-duration $Frequency-easing backwards;
  transform: translateY(0%);
  transition: transform $Frequency-duration ease;
  display: flex;
  justify-content: left;
  align-items: center;

  @for $i from 1 through 6 {
    amp;:nth-of-type(#{$i}) {
      animation-delay: calc(#{$i} * #{$Frequency-delay});
    }
  }
}

.Frequency--closing .Frequency-listItem {
   animation: exit $Frequency-exitDuration $Frequency-easing both 1;
   transform: translateY(100%);
   transition: transform $Frequency-exitDuration ease;

   @for $i from 6*-1 through -1 {
      amp;:nth-of-type(#{abs($i)}) {
         animation-delay: calc(#{abs($i)} * #{$Frequency-exitDelay}   2s);
      }
    }
 }

@keyframes enter {
  from {
      opacity: 0;
      padding: 0;
      margin: 0;
      max-height: 0;
      transform: scale(.7);
  }
}

@keyframes exit {
   from {
       opacity: 1;
       max-height: 100%;
       transform: scale(1);
   }
   to {
      opacity: 0;
      padding: 0;
      margin: 0;
      max-height: 0;
      transform: scale(.7);
  }
 }
 

Вот CODESANBOX, если вы хотите его протестировать

Любая помощь будет принята с благодарностью!

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

1. Похоже, это работает: codesandbox.io/s/1v556xj14j (В основном я изменил основной файл, но также убрал 2s задержку из анимации закрытия.

2. @Chris G Это сработало отлично, спасибо. Не думал об использовании 2 таймаутов!