在 setInterval 循环中使用 setter 函数时,clearInterval 不起作用
When using setter function inside a setInterval loop, clearInterval is not working
基本上,我试图制作一个计数器,它在我按下开始按钮时开始计算秒数,并在我按下停止按钮时停止计数,并将其存储在 sec[=24 中=].
当我按下开始按钮时,会触发一个 handleStart 函数,它将开始变量设置为 1。此外,setInterval 开始重复(每秒)一个 setter 函数,该函数会增加 sec 一个。这个 setInterval 还有一个条件语句,当 start 变为 0 时清除 setInterval;
当我按下停止按钮时,另一个函数 handleStop 被触发,将 start 设置为 0。如果 setInterval 正在 运行,它应该看到 start 现在是 0 并且应该清除应该停止更新的 setInterval 秒variable/state。但这是行不通的。当我开始登录时它仍然是 1,即使在按下停止变量之后也是如此。如果我在 handleStop 函数中记录开始,它记录为 0 但这没有反映在 handleStart 函数的进一步日志语句中。
此外,当我注释掉 handleStart 函数中的 setSec((prev)=> {return prev+1})
行时,一切正常(按下停止按钮后 setInterval 被清除),所以我猜想有一些关于 useState 功能的东西我不明白。
谁能告诉我怎么了?
export default function Bug() {
let start = 0
let [sec, setSec] = useState(0)
let repeat
function handleStart() {
start = 1
repeat = setInterval(() => {
setSec((prev) => { return prev + 1 })
console.log(start);
if (start === 0) {
clearInterval(repeat)
}
}, 100);
}
function handleStop() {
start = 0
//clearInterval(repeat) //this clearInterval is not working either
}
return (
<div>
<p>{sec}</p>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
}
抱歉,如果此类问题已在此处得到解答。我试图搜索类似的问题,但找不到。
您的 repeat
变量不会在渲染之间持续存在,因此每次您调用 setSec
它都会重新渲染。
一个选择是使用与您的计时器变量相同的想法来存储您的重复变量。
const Bug = () => {
const [sec, setSec] = useState(0)
const [repeat,setRepeat] = useState()
const handleStart = () => {
setRepeat(setInterval(() => {
setSec((prev) => { return prev + 1 })
}, 1000));
}
const handleStop = () => {
clearInterval(repeat)
}
return (
<div>
<p>{sec}</p>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
}
ReactDOM.render(<Bug/>,document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<script>var { useReducer, useEffect, useState, useRef, useCallback } = React</script>
<div id="root"></div>
基本上,我试图制作一个计数器,它在我按下开始按钮时开始计算秒数,并在我按下停止按钮时停止计数,并将其存储在 sec[=24 中=].
当我按下开始按钮时,会触发一个 handleStart 函数,它将开始变量设置为 1。此外,setInterval 开始重复(每秒)一个 setter 函数,该函数会增加 sec 一个。这个 setInterval 还有一个条件语句,当 start 变为 0 时清除 setInterval;
当我按下停止按钮时,另一个函数 handleStop 被触发,将 start 设置为 0。如果 setInterval 正在 运行,它应该看到 start 现在是 0 并且应该清除应该停止更新的 setInterval 秒variable/state。但这是行不通的。当我开始登录时它仍然是 1,即使在按下停止变量之后也是如此。如果我在 handleStop 函数中记录开始,它记录为 0 但这没有反映在 handleStart 函数的进一步日志语句中。
此外,当我注释掉 handleStart 函数中的 setSec((prev)=> {return prev+1})
行时,一切正常(按下停止按钮后 setInterval 被清除),所以我猜想有一些关于 useState 功能的东西我不明白。
谁能告诉我怎么了?
export default function Bug() {
let start = 0
let [sec, setSec] = useState(0)
let repeat
function handleStart() {
start = 1
repeat = setInterval(() => {
setSec((prev) => { return prev + 1 })
console.log(start);
if (start === 0) {
clearInterval(repeat)
}
}, 100);
}
function handleStop() {
start = 0
//clearInterval(repeat) //this clearInterval is not working either
}
return (
<div>
<p>{sec}</p>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
}
抱歉,如果此类问题已在此处得到解答。我试图搜索类似的问题,但找不到。
您的 repeat
变量不会在渲染之间持续存在,因此每次您调用 setSec
它都会重新渲染。
一个选择是使用与您的计时器变量相同的想法来存储您的重复变量。
const Bug = () => {
const [sec, setSec] = useState(0)
const [repeat,setRepeat] = useState()
const handleStart = () => {
setRepeat(setInterval(() => {
setSec((prev) => { return prev + 1 })
}, 1000));
}
const handleStop = () => {
clearInterval(repeat)
}
return (
<div>
<p>{sec}</p>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
}
ReactDOM.render(<Bug/>,document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<script>var { useReducer, useEffect, useState, useRef, useCallback } = React</script>
<div id="root"></div>