onClick 减少每次点击的次数而不是启动计时器
onClick decreases the number with each click rather than starting the timer
所以我正在用 React 构建一个冥想应用程序。为了简单起见,我给了它 25 分钟的倒计时。
我希望在单击按钮时开始倒计时。但是,当我将 setInterval 包装在 handleClick() 函数中时,每次点击秒数都会减少,而不是触发一次倒计时。
感谢任何帮助,提前致谢。
import React, { Component, useState } from "react";
function Timer() {
const [minutes, setMinutes] = useState(25);
const [seconds, setSeconds] = useState(0);
function handleClick() {
console.log('Clicked');
let interval = setInterval(() => {
clearInterval(interval);
if (seconds === 0) {
if (minutes !== 0) {
setSeconds(59);
setMinutes(minutes - 1);
} else {
setSeconds(seconds - 1);
}
}, 1000)
}
const timerMinutes = minutes < 10 ? `0${minutes}`: minutes;
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;
return (
<>
<div className="grey-box">
<div className="number-box">
<h2 className="timer-text">{timerMinutes}:{timerSeconds}</h2>
</div>
<div className="buttons-container">
<button className="timer-button" onClick={handleClick}>
<img
className="play"
src="https://img.icons8.com/ios-glyphs/90/ffffff/play--v1.png"
/>
</button>
</div>
</div>
</>
);
}
export default Timer;
您声明每次点击都会减去一分钟:
setMinutes(minutes - 1);
如果希望定时器只设置一次,可以查看是否设置过,如果设置过,则中止handleClick函数。计时器的 let 声明将仅在该代码块中可用(根据 运行)。因此,当发生另一次点击时,您将无法访问计时器。使用“this.interval”(函数范围)或“var interval”(global/window 范围),然后您将能够在 handleClick 函数的顶部检查是否已设置计时器。
if (this.interval) return;
OR
if (interval) return;
您正在以更复杂的方式创建计时器。我制作了一个示例,可以涵盖此用例以及一些边缘情况。
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function ClearTimer(TimerHndlRef) {
clearInterval(TimerHndlRef.current);
TimerHndlRef.current = null;
}
function App() {
const TimerHndlRef = useRef();
const [seconds, secondsSet] = useState(5);
const onClick = () => {
if (TimerHndlRef.current) {
ClearTimer(TimerHndlRef);
return;
}
TimerHndlRef.current = setInterval(
() =>
secondsSet((s) => {
const v = s - 1;
if (v > 0) return v;
ClearTimer(TimerHndlRef);
return 0;
}),
1000,
);
};
const onChange = (e) => secondsSet(parseInt(e.target.value, 10));
useEffect(() => {
return () => {
if (!TimerHndlRef.current) return;
ClearTimer(TimerHndlRef);
};
}, []);
const mLeft = Math.floor(seconds / 60);
const sLeft = seconds - mLeft * 60;
const mDisp = mLeft < 10 ? `0${mLeft}` : mLeft;
const sDisp = sLeft < 10 ? `0${sLeft}` : sLeft;
return (
<div>
<p>
<input type="number" value={seconds} onChange={onChange} /> = {mDisp}m +{" "}
{sDisp}s
</p>
<button onClick={onClick}>Test</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
所以我正在用 React 构建一个冥想应用程序。为了简单起见,我给了它 25 分钟的倒计时。
我希望在单击按钮时开始倒计时。但是,当我将 setInterval 包装在 handleClick() 函数中时,每次点击秒数都会减少,而不是触发一次倒计时。
感谢任何帮助,提前致谢。
import React, { Component, useState } from "react";
function Timer() {
const [minutes, setMinutes] = useState(25);
const [seconds, setSeconds] = useState(0);
function handleClick() {
console.log('Clicked');
let interval = setInterval(() => {
clearInterval(interval);
if (seconds === 0) {
if (minutes !== 0) {
setSeconds(59);
setMinutes(minutes - 1);
} else {
setSeconds(seconds - 1);
}
}, 1000)
}
const timerMinutes = minutes < 10 ? `0${minutes}`: minutes;
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;
return (
<>
<div className="grey-box">
<div className="number-box">
<h2 className="timer-text">{timerMinutes}:{timerSeconds}</h2>
</div>
<div className="buttons-container">
<button className="timer-button" onClick={handleClick}>
<img
className="play"
src="https://img.icons8.com/ios-glyphs/90/ffffff/play--v1.png"
/>
</button>
</div>
</div>
</>
);
}
export default Timer;
您声明每次点击都会减去一分钟:
setMinutes(minutes - 1);
如果希望定时器只设置一次,可以查看是否设置过,如果设置过,则中止handleClick函数。计时器的 let 声明将仅在该代码块中可用(根据 运行)。因此,当发生另一次点击时,您将无法访问计时器。使用“this.interval”(函数范围)或“var interval”(global/window 范围),然后您将能够在 handleClick 函数的顶部检查是否已设置计时器。
if (this.interval) return;
OR
if (interval) return;
您正在以更复杂的方式创建计时器。我制作了一个示例,可以涵盖此用例以及一些边缘情况。
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function ClearTimer(TimerHndlRef) {
clearInterval(TimerHndlRef.current);
TimerHndlRef.current = null;
}
function App() {
const TimerHndlRef = useRef();
const [seconds, secondsSet] = useState(5);
const onClick = () => {
if (TimerHndlRef.current) {
ClearTimer(TimerHndlRef);
return;
}
TimerHndlRef.current = setInterval(
() =>
secondsSet((s) => {
const v = s - 1;
if (v > 0) return v;
ClearTimer(TimerHndlRef);
return 0;
}),
1000,
);
};
const onChange = (e) => secondsSet(parseInt(e.target.value, 10));
useEffect(() => {
return () => {
if (!TimerHndlRef.current) return;
ClearTimer(TimerHndlRef);
};
}, []);
const mLeft = Math.floor(seconds / 60);
const sLeft = seconds - mLeft * 60;
const mDisp = mLeft < 10 ? `0${mLeft}` : mLeft;
const sDisp = sLeft < 10 ? `0${sLeft}` : sLeft;
return (
<div>
<p>
<input type="number" value={seconds} onChange={onChange} /> = {mDisp}m +{" "}
{sDisp}s
</p>
<button onClick={onClick}>Test</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);