问题描述
我正在创建一个带有按钮来开始和停止时间的秒表,但是我遇到了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>
}
顺便说一句,不需要使用状态。当然,如果不需要保持计时器状态,则可以使用简单的变量。