簡體   English   中英

我的 clearInterval function 不能在 React 中工作有什么原因嗎?

[英]Is there a reason why my clearInterval function isnt working in React?

我創建了一個簡單的計時器腳本,初始化時間為 10 秒以進行測試。 我遇到的問題是暫停計時器按鈕沒有按預期工作。

import React, { useState } from 'react';

function App() {

  const [time, updateTime] = useState(() => { return 10 });
  const [timerRunning, setTimerRunning] = useState(false);
  
  let minutes = Math.floor(time / 60);
  let seconds = time % 60;
  let interval;

  function startTimer() {
    setTimerRunning(true);
    interval = setInterval( function() {
      updateTime(previousTime => previousTime === 0 ? previousTime : previousTime - 1);
    }, 1000);
  }

  function pauseTimer() {
    setTimerRunning(false);
    clearInterval(interval);
  }

  function restartTimer() {
    setTimerRunning(false);
    updateTime(() => {return 10});
  }

  return (
    <>
      <p>{minutes > 9 ? minutes : "0" + minutes}:{seconds > 9 ? seconds : "0" + seconds}</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={pauseTimer}>Pause</button>
      <button onClick={restartTimer}>Restart</button>
    </>
  )
}

export default App;

我想要暫停按鈕來暫停計時器。 最終,我將根據應用程序的 state 和時間值制作條件語句,讓每個按鈕出現,但暫停按鈕是我目前的障礙。

我首先有一個單獨的倒計時 function ,它使用條件來停止時間匹配計數器的時間(如下) 我想到了一種不太復雜的方法,可以讓我省略計數器變量(上圖) 我不確定哪個選項更好,或者是否阻止clearInterval function 正常工作。 clearInterval function 在倒計時 function if 語句內工作,但在它之外不能工作。

import React, { useState } from 'react';

function App() {

  const [time, updateTime] = useState(() => { return 10 });
  const [timerRunning, setTimerRunning] = useState(false);
  
  let counter = 0;
  let minutes = Math.floor(time / 60);
  let seconds = time % 60;
  let interval;

  function countdown() {
    counter++;
    if ( counter === time ) {
       setTimerRunning(false);
       clearInterval(interval);
    }
      updateTime(previousTime => previousTime - 1);
  }
  

  function startTimer() {
    setTimerRunning(true);
    interval = setInterval(countdown, 1000);
  }

  function pauseTimer() {
    setTimerRunning(false);
    clearInterval(interval);
  }

  function restartTimer() {
    setTimerRunning(false);
    updateTime(() => {return 10});
  }



  return (
    <>
      <p>{minutes > 9 ? minutes : "0" + minutes}:{seconds > 9 ? seconds : "0" + seconds}</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={pauseTimer}>Pause</button>
      <button onClick={restartTimer}>Restart</button>
    </>
  )
}

export default App;

基本上你不能創建let interval; 並為其分配一個 setInterval,如interval = setInterval(countdown, 1000);

因為每次重新渲染都會有新的let interval;

您需要做的是創建一個不會在 re-redners 上更改的變量,您可以使用useRef

const interval = useRef(null);
.....
function startTimer() {
    interval.current = setInterval(countdown, 1000);
}
....
function pauseTimer() {
   clearInterval(interval.current);
}

而且我認為您不需要const [timerRunning, setTimerRunning] = useState(false);

在這里找到一個演示

基本上,當功能組件重新渲染時,它將從上到下執行,如果您使用 like let counter = 0; ,然后在每次重新渲染時,它將初始化為 0,如果您需要在每次重新渲染中保留您的值,您可能需要一些鈎子(例如:useState,useRef ...),在這種情況下, useRef可以解決問題(因為在每次重新渲染中只需要一個 setInterval 並且 useRef 會給你以前的值,它不會像一般變量一樣重新初始化)

那是我的解決方案

而不是 startTime function,我使用 useEffect

  useEffect(()=>{
    interval = timerRunning && setInterval(() => {
      updateTime(previousTime => previousTime === 0 ? previousTime : previousTime - 1);
    }, 1000);
    return ()=> clearInterval(interval)
  },[timerRunning])

並在 onClick 啟動按鈕

<button onClick={()=> setTimerRunning(true)}>Start</button>

我希望它有用

你必須使用 useEffect,像這樣:

 const handleStart = () => {
    setChangeValue(true)
  }

  const handlePause = () => {
    setChangeValue(false)
    pauseTimer()
  }

  const handleRestart = () => {
    setInitialState()
    setChangeValue(true)
  }

  useEffect(() => {
    if (changeValue) {
      const interval = setInterval(() => {
        startTimer()
      }, 100)
      return () => clearInterval(interval)
    }
  }, [changeValue])

你有三個按鈕來啟動、暫停和重新啟動,用它們調用這些(handleStart, handlePause, handleRestart)函數

暫無
暫無

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

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