我想使用
setInterval
停止 clearInterval()
。但intervalId
就是undefined
。我不知道为什么。
import { useState } from 'react';
function Component() {
const [counter, setCounter] = useState(0);
function addToCounter() {
setCounter((c) => c + 1);
}
let intervalId;
function runInterval() {
intervalId = setInterval(addToCounter, 1000);
console.log(intervalId);
}
function stopInterval() {
clearInterval(intervalId);
console.log(intervalId);
}
return (
<>
<p>Value :{counter}</p>
<button onClick={runInterval}>start interval</button>
<button onClick={stopInterval}>stop interval</button>
</>
);
}
export default Component;
线路时有效
intervalId = setInterval(addToCounter, 1000);
替换为
intervalId = setInterval(()=>console.log(intervalId), 1000);
addToCounter
更新状态,重新渲染组件,该组件声明一个新的 intervalId
,因此您的间隔已丢失。
有多种方法可以实现总体目标,包括使用
useEffect
。为了对当前代码进行最少的更改,只需将间隔标识符存储在状态中至少应该在渲染过程中保留它。例如:
function Component() {
const [counter, setCounter] = useState(0);
const [intervalId, setIntervalId] = useState();
function addToCounter() {
setCounter((c) => c + 1);
}
function runInterval() {
setIntervalId(setInterval(addToCounter, 1000));
}
function stopInterval() {
clearInterval(intervalId);
}
return (
<>
<p>Value :{counter}</p>
<button onClick={runInterval}>start interval</button>
<button onClick={stopInterval}>stop interval</button>
</>
);
}
export default Component;
答案在于 React 的工作原理。在第一种情况下,您将函数 addToCounter 传递给间隔。函数 addToCounter 有 setCounter ,它是来自 useState 挂钩的 setter 。当设置新状态时,React 会重新渲染组件。在每个重新渲染中,intervalId 在开始时都有未定义的值。为此,它不会停止间隔,因为 id 丢失了。
在第二种情况下 () => console.log() 不触发重新渲染,id 保存在 IntervalId 中并且有效。