繁体   English   中英

setInterval 开始和停止行为

[英]setInterval start and stop behavior

我正在创建一个秒表,它有一个按钮来开始和停止时间,但我在 setInterval 行为方面遇到了问题。

当在 React 的功能组件级别声明时,它会在安装后运行。
例子:

const Timer = () => {
    const timer = setInterval(() => console.log('running'), 1000)
}

当我在 function 中声明它时,它不会运行,直到 function 被调用,但我无法让它停止。

const Timer = () => {
    const [start, setStart] = useState(false)

    const startStopTimer = () => {
        const timer = setInterval(() => console.log('running'), 1000)
    }

    return (<Button 
                onClick={() => {
                   setStarted(!start)
                   startStopTimer()
                }
             > Start/Stop </Button>)
}

然后我尝试在 function 中添加clearInterval()并在start === false时有条件地调用它。 在这个实现中,第一个按钮点击什么都不做。 第二次单击启动计时器,但无法停止。

const Timer = () => {
    const [start, setStart] = useState(false)

    const startStopTimer = () => {
        let timer = setInterval(() => console.log('running'), 1000)
        if (!started) clearInterval(timer)
    }

    return (<Button 
                onClick={() => {
                   setStarted(!start)
                   startStopTimer()
                }
             > Start/Stop </Button>)
}

Ciao,我建议你像这样修改你的代码:

const Timer = () => {
    //const [start, setStart] = useState(false) do not use state for scripting reasons
    let timer = null;

    const startStopTimer = () => {
        if(!timer) timer = setInterval(() => console.log('running'), 1000)
        else {
           clearInterval(timer)
           timer = null
        } 
    }

    return (<Button 
                onClick={() => {
                   //setStarted(!start)
                   startStopTimer()
                }
             > Start/Stop </Button>)
}

说明: timer应该在startStopTimer之外定义,否则,每次启动startStopTimer时,都会创建一个新timer

好的,这很容易,但现在是重要的部分:出于脚本原因,我强烈建议您不要使用 react state。 react state 应该仅用于渲染原因。 为什么? 因为钩子是异步的,如果您在使用setStart后立即读取start ,您将读取旧值。

timer变量是本地的,每次调用sartStopTimer()时,它只在sartStopTimer()范围内生成新的timer ,当清除超时时,您只清除最近生成的计时器,而不是以前的timer

let timer;
const startStopTimer = () => {
        timer = setInterval(() => console.log('running'), 1000)
        if (!started) clearInterval(timer)
    }

使timer成为全局变量。

这应该让你开始。

尝试这个:

const Timer = () => {
    const [timerId, setTimerId] = useState(null)
        
    function startStopTimer(){
      if (timerId) {
        clearInterval(timerId)
        setTimerId(null)
      } else {
        setTimerId(setInterval(() => console.log('hello'), 1000))
      }
    }
    return <button onClick={startStopTimer}> Start/Stop </button>
}

顺便说一句,没有必要使用 state。 如果您不需要保留计时器 state 您当然可以使用普通变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM