我正在使用React pomodoro时钟,并且卡在setifout()的if / else上。这是我的代码:
React.useEffect(() => {
if(props.isOn === true) {
if(props.timeLeft <= 0) {
setTimeout(function() {
if(props.activeClockType === 'Session') {
props.handleClockType('Break');
props.handleTimeLeft(props.breakLength * 60);
} else {
props.handleClockType('Session');
props.handleTimeLeft(props.sessionLength * 60);
}
}, 1000);
}
const id = setInterval(count, 1000);
return () => clearInterval(id);
}
});
当时钟转到00:00时,它将停止1秒钟,然后显示Break(间隔)并将计时器设置为breakLength。很好,但是经过1秒后,它没有倒计时,而是变回Session并计算sessionLength。
当我删除setTimeout (在CodePen中注释)时,它可以正常工作,但它不会在00:00停止1秒,但会立即更改Break看起来很丑的内容。
如何在计数其他activeClockType之前使其在00:00停止1秒?
我整个晚上都在寻找任何线索,但我仍然不知道哪里出了问题。我试图将setTimeout与if的每种可能组合都放在同一位置。在this topic中,我怀疑我可能应该使用clearTimeout,但也可以尝试以任何组合使用它,但一无所获。
或者也许我应该尝试使用useEffect()以外的另一种方式来运行倒计时?早些时候,我使用componentWillReceiveProps在类组件(在CodePen中进行了注释)中创建了工作计时器,但该计时器已被弃用,并且我尝试在其他函数上进行更改也没有效果。我不完全了解这个效果钩,但这是我found计数良好的唯一方法。而且比类组件要短。
Here是我在CodePen上的完整代码
谢谢。
答案 0 :(得分:2)
我认为这里有两个问题:
1)每次使用钩子设置状态时,都会触发React.useEffect,如果将状态设置两次,则React.useEffect将被触发两次。
2)使用setTimeout替换setInterval以避免更新状态过多。
问题显示如下:
React.useEffect(() => {
if(props.isOn === true) {
if(props.timeLeft <= 0 && !changeClockType) {
setTimeout(function() {
if(props.activeClockType === 'Session') {
props.handleClockType('Break'); // ==> Fired update and then excuted React.useEffect
props.handleTimeLeft(props.breakLength * 60); // ==> Fired update again and then excuted React.useEffect again
} else {
props.handleClockType('Session');
props.handleTimeLeft(props.sessionLength * 60);
}
}, 1000);
}
const id = setTimeout(count, 1000); // ==> modify setInterval to setTimeout
return () => clearInterval(id);
}
});
我尝试修改如下代码:
let changeClockType = false; // ==> Should be put here because it couldn't be put in the function component
function Timer(props) {
const count = () => props.handleTimeLeft(props.timeLeft - 1);
function startStop() {
props.handleIsOn(props.isOn === false ? true : false);
}
React.useEffect(() => {
console.log("step 1");
if(props.isOn === true) { console.log("step 2");
if(props.timeLeft <= 0 && !changeClockType) { console.log("step 3");
setTimeout(function() {
if(props.activeClockType === 'Session') { console.log("step 4");
changeClockType = true;
props.handleClockType('Break'); // ==> Fired update and then excuted React.useEffect
console.log("Change to Break")
props.handleTimeLeft(props.breakLength * 60); // ==> Fired update again and then excuted React.useEffect again
changeClockType = false;
console.log("Set breakLength")
} else { console.log("step 5");
changeClockType = true;
props.handleClockType('Session');
props.handleTimeLeft(props.sessionLength * 60);
changeClockType = false;
}
}, 1000);
}
const id = setTimeout(count, 1000); // ==> modify setInterval to setTimeout
return () => clearInterval(id);
}
});
代码不是很干净,但是可以很好地运行。