簡體   English   中英

反應:即使在使用 clearInterval 清除計時器后,Setinterval 也不會停止

[英]React: Setinterval is not stopping even after clearing the timer using clearInterval

我制作了一個基本的幻燈片演示,其中選中復選框幻燈片已啟用。 問題是即使我取消選中復選框,一旦啟用幻燈片放映也無法禁用。 根據 muy 的理解,我正在學習計時器並使存儲計時器的 state 無效,但幻燈片繼續放映。

具體來說,這部分在復選框更新時被調用:

useEffect(() => {
  if (isTrue) {
    setSlideTimer(() => {
      return setInterval(() => {
        forwardButton.current.click();
      }, slideDuration);
    });
  } else {
    clearInterval(slideTimer);
    setSlideTimer(null);
  }
}, [isTrue]);

從瀏覽器日志中可以明顯看出計時器確實被清除了。 雖然有警告"... component is changing an uncontrolled input of type checkbox to be controlled" ,但我不確定這是否是罪魁禍首。

問題

問題是您缺少對sliderTimer state 的依賴。

useEffect(() => {
    if (isTrue) {
      setSlideTimer(() => {
        return setInterval(() => {
          forwardButton.current.click();
        }, slideDuration);
      });
    } else {
      clearInterval(slideTimer);
      setSlideTimer(null);
    }
  }, [isTrue]);

解決方案

通常不要將計時器 ID 存儲在 state 中。如果您需要在useEffect掛鈎之外訪問計時器 ID,則使用 React ref,否則只需將其緩存在useEffect掛鈎的回調中。 在這種情況下,您將希望使用 ref 來保存sliderTimer id 值,以便在組件卸載的情況下也可以清除它。

例子:

const sliderTimerRef = React.useRef();

useEffect(() => {
  // Clear any running intervals on component unmount
  return () => clearInterval(sliderTimerRef.current);
}, []);

useEffect(() => {
  if (isTrue && forwardButton.current) {
    sliderTimerRef.current = setInterval(
      forwardButton.current.click,
      slideDuration
    );
  } else {
    clearInterval(sliderTimerRef.current);
  }
}, [isTrue]);

附加問題

從瀏覽器日志中可以明顯看出計時器確實被清除了。 雖然有警告"... component is changing an uncontrolled input of type checkbox to be controlled" ,但我不確定這是否是罪魁禍首。

valuechecked prop 從未定義值更改為已定義值時,通常會出現這種情況。 確保選中的 state 是最初定義的,即使只是false

嘗試這個!

  useEffect(() => {
    let interval;
    if (isChecked) {
      interval = setInterval(() => {
        forwardButton.current.click();
      }, 1000); // change it
    }

    return function cleanup() {
      clearInterval(interval);
      console.log('Clear timer');
    };
  }, [isChecked]);

另一種方法是使用setTimeout()方法。 為此,您需要創建一個新的 state clicks (或任何其他名稱),每次更改時都會觸發useEffect ,從而使setTimeoutsetInterval一樣工作

const [clicks, setClicks] = useState(0)

useEffect(() => {
  if(isChecked){
    setTimeout(() => { 
      forwardButton.current.click()
      setClicks(clicks + 1)
    }, slideDuration)
  }
}, [isChecked, clicks])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM