为什么 setInterval 没有像在 vanilla JS 中那样在 REACT 中被清除

Why is setInterval not being cleared in REACT the same way as it is in vanilla JS

当我发现这种奇怪的行为时,我正在创建一个简单的秒表组件。我想要一个暂停按钮来删除一个间隔,但它什么都不做(点击暂停按钮后间隔仍然是 运行)。我觉得很奇怪,因为相同的代码在 vanilla js 中很容易工作,它会使计时器停止计数。

  const [timer,setTimer] = useState(0)
  let interval;

  const tick = () =>{
    setTimer(prev=>prev+1)
  }

  const startInterval = () =>{
    interval = setInterval(tick,1000)
  }

  const pauseInterval = () =>{
    clearInterval(interval)
  }
  
  return (
    <div>
      <h1>Timer: {timer}</h1>
      <button onClick={startInterval}>start</button>
      <button onClick={pauseInterval}>pause</button>
    </div>
  )

解决这个问题并使其发挥作用的唯一方法是创建另一个状态,我将在该状态下保持活动间隔。

const [timer,setTimer] = useState(0)
  const [activeInterval,setActiveInterval] = useState(null)
  let interval;

  const tick = () =>{
    setTimer(prev=>prev+1)
  }

  const startInterval = () =>{
    interval = setInterval(tick,1000)
    setActiveInterval(interval)
  }

  const pauseInterval = () =>{
    clearInterval(activeInterval)
    setActiveInterval(null)
  }
  
  return (
    <div>
      <h1>Timer: {timer}</h1>
      <button onClick={startInterval}>start</button>
      <button onClick={pauseInterval}>pause</button>
    </div>
  )

为什么我不能像在第一个代码示例中那样删除间隔?

您必须使用 useRef.

来保存对您的间隔的引用

目前您正在将间隔的键存储在函数体 (let interval;) 中定义的变量中,问题是在组件被重新渲染后,let interval 失去了它值。

要在渲染之间保留状态,您可以使用 useRefuseState

const intervalContainer = useRef();

...

const startInterval = () => {
    intervalContainer.current = setInterval(tick,1000)
    setActiveInterval(interval)
}

const pauseInterval = () => {
    clearInterval(intervalContainer.current)
    setActiveInterval(null)
}