I'm trying to code a simple timer with two buttons. Start Button: timer will be added by one every 10ms. Lap Button: timer will be pushed to an array and also showed in a pre tag. Unfortunately, Lap Button doesn't work. can anybody help me figure this issue out? TY.
import { useState } from "react";
import { formatSeconds } from "./format";
let interval : NodeJS.Timer;
function App() {
const [buttonName, setButtonName] = useState("Start");
let [timer, setTimer] = useState(0);
const laps : Array<number> = [];
const handleStartClick = () => {
setButtonName(buttonName === "Start" ? "Stop" : "Start")
if(buttonName === "Start"){
interval = setInterval(() => {
setTimer(timer += 1)
}, 10);
}else{
clearInterval(interval)
}
}
const handleLapClick = () => {
laps.push(timer);
}
return (
<div>
<button onClick={handleStartClick}>{buttonName}</button>
<button onClick={handleLapClick}>Lap</button>
<div>
<p>Elapsed:</p> <pre id="elapsed">{formatSeconds(timer)}</pre>
</div>
<hr />
<div id="laps">
<p>Laps:</p>
{laps?.map((item) => {
return <pre key={item}>{formatSeconds(item)}</pre>;
})}
</div>
</div>
);
}
export default App;
Problem:: Your component is not updating on handleLapClick
function.
Solution:
laps
to a state
variable using the useState hook
laps array
, update the laps state
by creating a new array
that includes the current timer value.(The reason behind creating a new array and then updating the laps state is because of a concept called, state immutability in React)
Changes to be made:
const [laps, setLaps] = useState<number[]>([]);
const handleLapClick = () => {
setLaps((prevLaps) => [...prevLaps, timer]);
};
Correct code after making changes:
import { useState } from "react";
import { formatSeconds } from "./format";
let interval: NodeJS.Timer;
function App() {
const [buttonName, setButtonName] = useState("Start");
const [timer, setTimer] = useState(0);
const [laps, setLaps] = useState<number[]>([]);
const handleStartClick = () => {
setButtonName((prevButtonName) =>
prevButtonName === "Start" ? "Stop" : "Start"
);
if (buttonName === "Start") {
interval = setInterval(() => {
setTimer((prevTimer) => prevTimer + 1);
}, 10);
} else {
clearInterval(interval);
}
};
const handleLapClick = () => {
setLaps((prevLaps) => [...prevLaps, timer]);
};
return (
<div>
<button onClick={handleStartClick}>{buttonName}</button>
<button onClick={handleLapClick}>Lap</button>
<div>
<p>Elapsed:</p> <pre id="elapsed">{formatSeconds(timer)}</pre>
</div>
<hr />
<div id="laps">
<p>Laps:</p>
{laps.map((item, index) => (
<pre key={index}>{formatSeconds(item)}</pre>
))}
</div>
</div>
);
}
export default App;