簡體   English   中英

如何在使用 useEffect() 執行的 function 上暫停/停止和間隔?

[英]How can I Pause/Stop and Interval on a function that is executed with useEffect()?

我正在 react.js 中制作倒數計時器腳本。 在計時器開始之前,會顯示 3 或 5 秒的倒計時,這兩個倒計時的數據都來自另一個組件。 我正在嘗試使用按鈕停止/暫停主倒計時。 我的問題是如何控制由 useEffect() 執行的 function 中的數據? 我正在嘗試為 btn 創建 state,但 state 的 scope 是 useEffect

import TimerForm from './components/TimerForm';

const CountDown = (props) => {

    const [timeLeft, setTimeLeft] = useState({
        minutes: 0,
        seconds: 0
    });
    const [counter, setCounter] = useState();
    const [startTimer, setStartTimer] = useState(false);
    const [result, setResult] = useState();
    let Interval;

    useEffect(() => {
        let count = null;
        if(startTimer){
            if(counter === 0){
                relog(result);
                clearInterval(count);
                return
            }
            count = setInterval(() => {
                setCounter((prevcounter) => prevcounter - 1);
            }, 1000);
            return () => clearInterval(count);
        } else {
            clearInterval(count);
        }

    }, [startTimer, counter]);

    const relog = useCallback((ForTime) => {
            console.log(testing);
            Interval = setInterval(() => {
                setTimeLeft({
                    seconds: ForTime % 60,
                    minutes: Math.floor(ForTime / 60)% 60
                });
                if(ForTime === 0){
                    clearInterval(Interval);
                    return;
                }
                ForTime--;
            },1000);      
        setStartTimer(false);
    },[]);
    
    const timerSettings = (data) => {
        setCounter(data.counter);
        setResult(data.result);
        setStartTimer(true);
    }

    return (
        <div>
        <section>
            <TimerForm onTimerSettings={timerSettings} />
            <span>{counter}</span>
            <div className="TimerClock">
                <span>{timeLeft.minutes}</span><span>:</span><span>{timeLeft.seconds}</span>
            </div>
            <div>
                <button type="button" className="btn btn-stop">Pause Button</button>
            </div>
        </section>
        </div>
    )
};

export default CountDown;```

您可以使用 useRef 存儲間隔計時器

  const countRef = useRef(null);

  useEffect(() => {
    if (startTimer) {
      if (counter === 0) {
        relog(result);
        clearInterval(countRef.current);
        return;
      }
      countRef.current = setInterval(() => {
        setCounter((prevcounter) => prevcounter - 1);
      }, 1000);
      return () => clearInterval(countRef.current);
    } else {
      clearInterval(countRef.current);
    }
 }, [startTimer, counter]);

您可以從 useEffect scope 獲取計時器

return (
  ...
   <button type="button" className="btn btn-stop" onClick={()=>{clearInterval(countRef.current)}}>Pause Button</button>
  ...
)

創建一個由 useEffect() 和 useRef() 使用的 useInterval 掛鈎。

/**
 * 
 * @param {Function} callback
 * @param {number|null} delay, stopped when delay is null
 */
function useInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  });

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

使用useInterval

function App() {
  const [delay, setDelay] = useState(null);
  const [counter, setCounter] = useState(0);

  useInterval(() => {
    setCounter((counter) => counter - 1);
  }, delay);

  const handleChangeDelay = () => {
    // stopped when delay is null
    setDelay(delay === null ? 1000 : null);
  };

  return (
    <div className="App">
      <p>
        <button onClick={handleChangeDelay}>trigger interval countdown</button>
      </p>
      <p>{counter}</p>
    </div>
  );
}

暫無
暫無

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

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