<div id="app"></app>
.red {
color: red;
}
const { useState, useEffect, useRef, useCallback, useMemo } = React;
const getThirdPartNumbers = (number) => {
if (!number && number < 0) return [];
return [Array(number + 1).keys()].slice(1).slice(0, number / 3);
};
const Timer = () => {
const [time, setTime] = useState("0");
const [isStart, setIsStart] = useState(false);
const startTimeRef = useRef(0);
const timerIdRef = useRef();
const thirdPartNumbers = useMemo(() => getThirdPartNumbers(startTimeRef.current), [startTimeRef.current]);
const clearTimer = () => {
if (timerIdRef.current) clearInterval(timerIdRef.current);
};
const start = () => {
if (startTimeRef.current < 0) return;
setIsStart(true);
};
const reset = useCallback(() => {
if (!isStart) return;
clearTimer();
timerIdRef.current = setInterval(() => setTime((t) => t - 1), 1000);
setTime(startTimeRef.current);
}, [startTimeRef.current]);
useEffect(() => {
if (!isStart) return;
reset();
return clearTimer;
}, [isStart, reset]);
useEffect(() => {
if (time === 0) reset();
}, [time, reset]);
return (
<>
<input
type="number"
onChange={(e) => {
const value = Number(e.target.value);
if (value > 0) startTimeRef.current = value;
}}
/>
<div>
<button onClick={start}>Start</button>
<p
className={thirdPartNumbers.includes(time) ? "red" : undefined}
>
{time}
</p>
<button onClick={reset}>Reset</button>
</div>
</>
);
};
ReactDOM.render(<Timer />, document.getElementById('app'));
View Compiled
This Pen doesn't use any external CSS resources.