【问题标题】:When using setter function inside a setInterval loop, clearInterval is not working在 setInterval 循环中使用 setter 函数时,clearInterval 不起作用
【发布时间】:2021-05-19 10:15:37
【问题描述】:

基本上,我试图制作一个计数器,当我按下开始按钮时开始计算秒数,当我按下停止按钮时停止计数,并将其保存在 sec 中。 p>

当我按下开始按钮时,会触发一个 handleStart 函数,它将 start 变量设置为 1。此外,setInterval 开始(每秒)重复一个将 sec 增加一的 setter 函数。这个setInterval还有一个条件语句,当start变为0时清除setInterval;

当我按下停止按钮时,另一个函数 handleStop 被触发设置 start 为 0。如果 setInterval 正在运行,它应该看到 start 现在是 0 并且应该清除应该停止更新 sec 变量的 setInterval /状态。但这不起作用。当我记录开始时,它仍然是 1,即使在按下停止变量之后也是如此。如果我在 handleStop 函数中记录 start ,它会记录为 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>
    )
}

抱歉,如果这里已经回答了这样的问题。我试图搜索一个类似的问题,但找不到。

【问题讨论】:

  • 如果要在handleStop 内清除,为什么还需要清除setInterval 回调内的间隔。
  • 我错过了评论其中一个。但是,clearInterval 都没有工作。
  • repeat 在每次渲染时都会重新初始化,因此在第一个刻度之后不再包含对间隔的引用。如果你想这样处理,要么使用 Ref,在回调中清除它,要么使用渲染生命周期来管理计时器的状态。
  • let repeat 移动到功能组件之外的位置
  • @devnull69,这不是一个好建议。组件应包含相关逻辑

标签: javascript reactjs setinterval use-state


【解决方案1】:

您的 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>

【讨论】:

  • 我认为 ref 在这里会更合适
猜你喜欢
  • 1970-01-01
  • 2021-05-18
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多