[英]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.