Reputation: 33
I was trying to make a stopwatch counter however when I call the "startTimer" function, the setInterval function is fired before the setStartTime (is fired after I click the start button for the second time).
import React from "react";
import { useState, useRef } from "react";
import RunButton from "./RunButton";
const RunTimer = () => {
const [timerOn, setTimerOn] = useState(false);
const [startTime, setStartTime] = useState(0);
const [timerTime, setTimerTime] = useState(0);
const timerInterval = useRef(null);
const startTimer = () => {
setTimerOn(true);
setStartTime(Date.now() - timerTime);
timerInterval.current = setInterval(() => {
setTimerTime(Date.now() - startTime);
}, 1000);
};
const stopTimer = () => {
setTimerOn(false);
clearInterval(timerInterval);
};
const resetTimer = () => {
setStartTime(0);
setTimerTime(0);
};
let seconds = Math.floor(timerTime / 1000) % 60;
let minutes = Math.floor(timerTime / 1000 / 60) % 60;
return (
<div className="text-6xl font-medium text-center">
{minutes < 10 ? `0${minutes}` : minutes}:
{seconds < 10 ? `0${seconds}` : seconds}
<div className="flex gap-10 justify-around">
<RunButton title="start" action={startTimer} />
<RunButton title="stop" color="red" action={stopTimer} />
<RunButton action={resetTimer} color="yellow" title="reset" />
</div>
</div>
);
};
export default RunTimer;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Upvotes: 0
Views: 237
Reputation: 485
I still dont understand why you need Date.now() to create a stopwatch.
What is wrong with:
const RunTimer = () => {
const [time, setTime] = useState(0);
const timerInterval = useRef(null);
const startTimer = () => {
if (!timerInterval.current) {
timerInterval.current = setInterval(() => {
setTime((t) => t + 1000);
}, 1000);
}
};
const stopTimer = () => {
clearInterval(timerInterval.current);
timerInterval.current = null;
};
const resetTimer = () => {
setTime(0);
};
const seconds = Math.floor(time / 1000) % 60;
const minutes = Math.floor(time / 1000 / 60) % 60;
useEffect(() => {
return () => clearInterval(timerInterval.current);
}, []);
return (
<div className="text-6xl font-medium text-center">
{minutes < 10 ? `0${minutes}` : minutes}:
{seconds < 10 ? `0${seconds}` : seconds}
<div className="flex gap-10 justify-around">
<button title="start" onClick={startTimer}>
start
</button>
<button title="start" onClick={stopTimer}>
stop
</button>
<button title="start" onClick={resetTimer}>
reset
</button>
</div>
</div>
);
};
Upvotes: 1