setInterval启动和停止行为

问题描述

我正在创建一个带有按钮来开始和停止时间的秒表,但是我遇到了setInterval行为的麻烦。

在React的功能组件级别中声明时,它将在安装后运行。
示例:

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

当我在函数中声明它时,它只有在调用函数后才能运行,但是我无法停止它。

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>)
}

然后我尝试在函数添加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状态。 react状态仅应出于渲染原因使用。为什么?由于钩子是异步的,如果您在使用start之后立即读取setStart,则会读取一个旧值。

,

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

顺便说一句,不需要使用状态。当然,如果不需要保持计时器状态,则可以使用简单的变量。