我正在研究番茄钟,但在休息后切换回番茄钟会话时遇到问题。
const start = () => {
//this stop function clears the pre-existing timer if there is any.
stop();
setTimerOn(true);
let interval = setInterval(() => {
setDisplayTime((prev) => {
//onBreak is false by default
if (prev <= 0 && !onBreak) {
setOnBreak(true);
return breakDuration;
}
// this if statement is not being executed
if (prev <= 0 && onBreak) {
setOnBreak(false);
return sessionDuration;
}
return prev - 1;
});
}, 1000);
//save the timer insatance in react state
setTimer(interval);
};
每当计时器变为 0 时,我都会更新 onBreak 的状态。但是当我在 React 开发工具中检查 onBreak 的状态时,只有在执行块时才首先更新状态,然后状态永远不会改变。代码在执行第一个 if 语句后进入无限循环,只有 breakSession 被一遍又一遍地执行。
答案 0 :(得分:0)
您的代码的问题在于您传递给 setInterval
的函数在创建时保存了 onBreak
的值;它无法获得 onBreak
的当前状态。 (我假设为 [onBreak, setOnBreak] = useState()
。)
传递可变状态的一种方法是useRef
。像这样:
const [onBreak, setOnBreak] = useState();
// Create a ref whose value is set automatically to onBreak
const onBreakRef = useRef();
useLayoutEffect(() => {
onBreakRef.current = onBreak;
}, [onBreak]);
const start = () => {
//this stop function clears the pre-existing timer if there is any.
stop();
setTimerOn(true);
let interval = setInterval(() => {
setDisplayTime((prev) => {
if (prev <= 0 && !onBreakRef.current) {
setOnBreak(true);
return breakDuration;
}
if (prev <= 0 && onBreakRef.current) {
setOnBreak(false);
return sessionDuration;
}
return prev - 1;
});
}, 1000);
//save the timer insatance in react state
setTimer(interval);
};
虽然这段代码感觉很乱。您能否在其他代码中执行 setOnBreak(false)
来响应 onBreak
是 true
?然后 setInterval
代码可以在 setOnBreak(true)
时无条件地prev <= 0
。