我想做一个倒计时器(25分钟)。这是App.js文件中的代码
import './App.css';
import React, { useState } from 'react';
function App() {
const [remainingTime, setRemainingTime] = useState(1500);
const [seconds, setSeconds] = useState(0);
const [minute, setMinute] = useState(remainingTime/60);
function timer() {
setRemainingTime(remainingTime-1);
let newMinute = remainingTime/60;
let minuteArray = [...newMinute.toString()];
setMinute(parseInt(minuteArray.slice(0,2).join("")));
setSeconds(remainingTime%60);
console.log(minute);
console.log(seconds);
}
return (
<div className="App">
<div className="pomodoro">
<div className="timer">{minute}:{seconds}</div>
<div className="button-container">
<button className="start" onClick={() => setInterval(timer, 1000)}>start</button>
</div>
</div>
</div>
);
}
export default App;
时间间隔不更新状态值。分钟值总是25秒值总是0。当我不使用setInterval而只像这样使用定时器函数时
<button className="start" onClick={timer}>start</button>
每次我点击开始按钮,值都会改变。有什么想法吗?我知道我也应该使用clearInterval,但是我不知道把它放在哪里。我应该创建一个包含setInterval和clearInterval的新函数吗?
2条答案
按热度按时间vzgqcmou1#
问题
timer
回调中的状态附件过时。**在间隔回调中,设置新值的标准形式不起作用,因为回调在每次运行时都使用相同的(未更新的)状态值:
***-这不起作用:***
setValue(value + 1)
溶液
使用另一种形式设置新值:
***-这将起作用:***
setValue((value) => value + 1)
此形式允许回调在每次运行时获取具有最新状态的新值。
详情
minute
和seconds
被认为是派生状态(从remainingTime
),因此不应将其存储在状态中,它很容易从状态计算出来。1.使用功能状态更新从先前状态更新
remainingTime
状态,而不是从回调入队的渲染周期状态更新remainingTime
状态。1.使用React参考值保持间隔定时器参考值,以便清除间隔。
1.使用
useEffect
钩子返回一个clean up函数,以清除组件卸载时的任何运行间隔。代码:
演示
由于这可能是一个后续问题,因此使用另一个
useEffect
"监听"remainingTime
状态,当时间达到0时,清除间隔,将remainingTime
重置回1500(* 用于显示 *),并显示任何报警或警报或番茄休息/时间表的任何内容。s5a0g9ez2#
每次重新渲染时,计时器设置为1500。在这里使用闭包,单击时激活。