gpt4 book ai didi

javascript - 单击按钮时不会重置作为计数器运行的时间间隔

转载 作者:行者123 更新时间:2023-12-03 14:15:43 25 4
gpt4 key购买 nike

我正在构建番茄计时器,计数器应从 25 分钟开始递减直至 0,然后运行 ​​5 分钟递减计时器。定时器和中断状态之后应该重置准备再次运行,到目前为止一切顺利。

但是,我在单击按钮运行时重置时间时遇到问题。我有一个函数 resetTimer 当前用于在每个周期结束时重新初始化计时器和中断计数,但如果在计时器或中断运行时单击(倒数到 0),则 resetTimer 确实运行了一秒钟,但随后计时器会像按钮触发事件之前一样继续运行。

我尝试过调用 resetTimerreturn 如果条件 resetClicked === true 调用该函数并且它会短暂运行但随后携带使用原来的计时器。

我还尝试设置一个初始化函数,在调用 start() 函数之前检查是否 resetClicked === true ,然后在 中再次调用它resetTimer 但也不起作用。

代码

import React, { useState } from "react";

export default function App() {
const [sessionLength, setSessionLength] = useState(25);
const [breakLength, setBreakLength] = useState(5);
const [timerRunning, setTimerState] = useState(false);
const [breakRunning, setBreakState] = useState(false);

let countdown;
let minutesToSecondsSession = sessionLength * 60;
let minutestoSecondsBreak = breakLength * 60;
const clear = () => clearInterval(countdown);

const start = () => {
if (timerRunning === false) {
setTimerState(true);
console.log("timer started");
const now = Date.now();
const then = now + minutesToSecondsSession * 1000;

displayTimeLeftSession(minutesToSecondsSession);

countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);

if (secondsLeft === 0) {
clear(countdown);
console.log("timer interval cleared");
breakTimer();
}

displayTimeLeftSession(secondsLeft);
}, 1000);
}
};
// end of timer function
//
// start of break timer
function breakTimer() {
if (breakRunning === false) {
setBreakState(true);
console.log("break timer started");
const now = Date.now();
const then = now + minutestoSecondsBreak * 1000;

displayTimeLeftBreak(minutestoSecondsBreak);

countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);

if (secondsLeft === 0) {
console.log("break interval cleared");
resetTimer();
return;
}

displayTimeLeftBreak(secondsLeft);
}, 1000);
}
}

function displayTimeLeftSession(minutesToSecondsSession) {
const minutes = Math.floor(minutesToSecondsSession / 60);
const remainderSeconds = minutesToSecondsSession % 60;

setSessionLength(`${minutes}:${remainderSeconds}`);
}

function displayTimeLeftBreak(minutesToSecondsBreak) {
const minutes = Math.floor(minutesToSecondsBreak / 60);
const remainderSeconds = minutesToSecondsBreak % 60;

setBreakLength(`${minutes}:${remainderSeconds}`);
}

// end of display timer logic

function incrementSession() {
if (sessionLength <= 60) {
setSessionLength(prev => prev + 1);
}
}

function decrementSession() {
if (sessionLength > 1) {
setSessionLength(prev => prev - 1);
}
}

function incrementBreak() {
if (breakLength < 60) {
setBreakLength(prev => prev + 1);
}
}

function decrementBreak() {
if (breakLength > 1) {
setBreakLength(prev => prev - 1);
}
}

const resetTimer = () => {
clear(countdown);
setTimerState(false);
setBreakState(false);
setSessionLength(0.05);
setBreakLength(0.05);
console.log("reset");
};

代码直到 return() 为止,省略了 JSX 以节省空间,只是将计时器渲染到页面上,添加嵌入时遇到问题。

https://codesandbox.io/s/fcc-pomodoro-clock-3rxfh?fontsize=14&hidenavigation=1&theme=dark

编辑:尝试将每个倒计时定义为单独的全局范围变量,然后在需要时为每个倒计时调用clearInterval,但同样的问题仍然存在。

import React, { useState, useRef } from "react";

export default function App() {
const [breakLength, setBreakLength] = useState(0.05);
const [sessionLength, setSessionLength] = useState(20);
const [timerRunning, setTimerState] = useState(false);
const [breakRunning, setBreakState] = useState(false);

let sessionCountdown;
let breakCountdown;
let minutesToSecondsSession = sessionLength * 60;
let minutestoSecondsBreak = breakLength * 60;
//const clear = () => clearInterval(countdown);

const start = () => {
if (timerRunning === false) {
setTimerState(true);
console.log("timer started");
const now = Date.now();
const then = now + minutesToSecondsSession * 1000;

displayTimeLeftSession(minutesToSecondsSession);

sessionCountdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);

if (secondsLeft === 0) {
clearInterval(sessionCountdown);
console.log("timer interval cleared");
breakTimer();
}

displayTimeLeftSession(secondsLeft);
}, 1000);
}
};
// end of timer function
//
// start of break timer
function breakTimer() {
if (breakRunning === false) {
setBreakState(true);
console.log("break timer started");
const now = Date.now();
const then = now + minutestoSecondsBreak * 1000;

displayTimeLeftBreak(minutestoSecondsBreak);

breakCountdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);

if (secondsLeft === 0) {
console.log("break interval cleared");
clearInterval(breakCountdown);
resetTimer();
return;
}

displayTimeLeftBreak(secondsLeft);
}, 1000);
}
}

function displayTimeLeftSession(minutesToSecondsSession) {
const minutes = Math.floor(minutesToSecondsSession / 60);
const remainderSeconds = minutesToSecondsSession % 60;

setSessionLength(`${minutes}:${remainderSeconds}`);
}

function displayTimeLeftBreak(minutesToSecondsBreak) {
const minutes = Math.floor(minutesToSecondsBreak / 60);
const remainderSeconds = minutesToSecondsBreak % 60;

setBreakLength(`${minutes}:${remainderSeconds}`);
}

// end of display timer logic

function incrementSession() {
if (sessionLength <= 60) {
setSessionLength(prev => prev + 1);
}
}

function decrementSession() {
if (sessionLength > 1) {
setSessionLength(prev => prev - 1);
}
}

function incrementBreak() {
if (breakLength < 60) {
setBreakLength(prev => prev + 1);
}
}

function decrementBreak() {
if (breakLength > 1) {
setBreakLength(prev => prev - 1);
}
}

const resetTimer = () => {
clearInterval(sessionCountdown);
clearInterval(breakCountdown);
setTimerState(false);
setBreakState(false);
setSessionLength(0.05);
setBreakLength(0.05);
console.log("reset");
};

最佳答案

TL;DR; 使用可以看到正在运行的沙箱 here

详细信息:

每次render执行 resetTimer() 的新闭包和其他功能被创建。如果你输入console.log(countdown)就在resetTimer()之前声明你会看到 countdown总是 undefined .

  1. 我真的怀疑在每个渲染上创建新函数是个好主意。
  2. 但要解决此特定问题,您可以保存 setInterval 的结果到国家稍后在resetTimer()中使用它
    const [countdown, setCountdown] = useState(undefined);
    但里面setInterval你仍然可以使用闭包,这更容易
    const interval = setInterval(() => {
    ...
    if (secondsLeft === 0) {
    clearInterval(interval);
    ...
    }
    ...
    }, 1000);
    setCountdown(interval) // save it to the state

关于javascript - 单击按钮时不会重置作为计数器运行的时间间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60738689/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com