const [lap, setLap] = useState([]);
function start(){
if(!isStart){
starting = Date.now() - elapsed;
isStart = true;
timer = setInterval(update, 1000);
console.log("timer is activated");
}
}
function stop(){
if(isStart){
isStart = false;
clearInterval(timer);
}
}
function reset(){
isStart = false;
elapsed = 0;
document.getElementById("time").textContent = "00:00:00";
clearInterval(timer);
starting = 0;
}
}
function update(){
var curr = Date.now();
elapsed = curr - starting;
var min = Math.floor(elapsed/(1000*60));
var sec = Math.floor((elapsed/1000)%60);
var msec = Math.floor((elapsed%1000)/10);
var time = [min, sec, msec]
time = time.map((element) => pad(element));
var time_str = time[0] + ":" + time[1] + ":" + time[2];
document.getElementById("time").textContent = time_str;
console.log(time_str)
}
const lap_update = (val) => {
setLap(lap => [...lap, val]);
}
<div id="lap" onClick={() => lap_update(document.getElementById("time").textContent)}>LAP</div>
The above are the code snippets for a Stopwatch is lap functionality.
Unfortunately, my lap_update function when clicked, is causing the start/stop/reset functions to malfunction.
(The stop function and reset function are not working, and the start function is double rendering).
I really am not able to understand why, and what changes are needed in the setLap statement.
Please help!
Trying to figure out the issue with the setLap statement which is causing the other functions to malfunction (till the Lap function is called, the program is running fine).
The issue with setLap
function causing other functions to malfunction in your React application likely stems from how state and side effects are being managed in React, especially when dealing with functional components and hooks.
Let's encapsulate your stopwatch logic within React component and make sure that state changes are managed correctly.
import React, { useState, useRef, useEffect } from 'react';
const Stopwatch = () => {
const [isRunning, setIsRunning] = useState(false);
const [elapsed, setElapsed] = useState(0);
const [laps, setLaps] = useState([]);
const timerRef = useRef(null);
const startTimeRef = useRef(0);
const start = () => {
if (!isRunning) {
startTimeRef.current = Date.now() - elapsed;
setIsRunning(true);
timerRef.current = setInterval(update, 1000);
console.log('timer is activated');
}
};
const stop = () => {
if (isRunning) {
setIsRunning(false);
clearInterval(timerRef.current);
}
};
const reset = () => {
setIsRunning(false);
setElapsed(0);
clearInterval(timerRef.current);
startTimeRef.current = 0;
document.getElementById('time').textContent = '00:00:00';
};
const update = () => {
const curr = Date.now();
setElapsed(curr - startTimeRef.current);
};
useEffect(() => {
if (!isRunning) return;
const interval = setInterval(() => {
const curr = Date.now();
setElapsed(curr - startTimeRef.current);
}, 1000);
return () => clearInterval(interval);
}, [isRunning]);
useEffect(() => {
const min = Math.floor(elapsed / (1000 * 60));
const sec = Math.floor((elapsed / 1000) % 60);
const msec = Math.floor((elapsed % 1000) / 10);
const time = [min, sec, msec].map(pad).join(':');
document.getElementById('time').textContent = time;
console.log(time);
}, [elapsed]);
const pad = (num) => (num < 10 ? '0' + num : num);
const lapUpdate = () => {
setLaps((laps) => [...laps, document.getElementById('time').textContent]);
};
return (
<div>
<div id="time">00:00:00</div>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
<button onClick={reset}>Reset</button>
<div id="lap" onClick={lapUpdate}>
LAP
</div>
<ul>
{laps.map((lap, index) => (
<li key={index}>{lap}</li>
))}
</ul>
</div>
);
};
export default Stopwatch;
Direct DOM Manipulation: Directly manipulating the DOM (document.getElementById('time').textContent
) can conflict with React's virtual DOM updates.
State Not Synchronized: Your functions were relying on local variables (isStart, elapsed) that were not synchronized with React's state management, leading to inconsistent behavior.
State Changes and Re-renders: Calling setLap
inside an event handler triggers a state update, causing a re-render. If the component isn't structured to handle re-renders properly, this can lead to unexpected behavior.