在 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>