Im making a timer progress bar animation in react. Im doing this using requestAnimationFrame(). The issue I have is that I cannot stop that animation with cancelAnimationFrame() despite setting an id to the animation and then reffering to that id while cancelling (handleStop func). Why?
Edit: Hmm, maybe it stops requestAnimationFrame() but it won't stop tranform animation that was already set?
const { useState, useEffect } = React;
const App = () => {
const totalTime = 10000;
const [timeLeft, setTimeLeft] = useState(null);
const [timerId, setTimerId] = useState(null);
useEffect(() => {
setTimeLeft(totalTime);
const start = performance.now();
const animate = (time) => {
const elapsedTime = time - start;
setTimeLeft((prevTimeLeft) => {
if (prevTimeLeft !== null && prevTimeLeft > 0) {
const remainingTime = Math.max(totalTime - elapsedTime, 0);
requestAnimationFrame(animate);
return remainingTime;
}
return 0;
});
};
const id = requestAnimationFrame(animate);
setTimerId(id);
return () => {
cancelAnimationFrame(id);
};
}, []);
const handleStop = () => {
if (timerId) {
cancelAnimationFrame(timerId);
setTimerId(null);
}
};
return (
<div>
<div className="progress-bar">
<div
style={{
transform: `scaleX(${timeLeft ? timeLeft / totalTime : 0})`,
}}
/>
</div>
<button onClick={handleStop}>Pause the animation</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
.progress-bar {
height: 10px;
width: 300px;
background-color: #fdb913;
border-radius: 10px;
overflow: hidden;
margin-top: 2rem;
margin-bottom: 3rem;
}
.progress-bar div {
background-color: grey;
height: 100%;
transform-origin: left center;
}
<div id="root">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
</div>
Maybe you can try these steps.
setState()callback function.useRef()instead ofuseState()to manage timer id.I wrote the code with those steps and it worked well in this code sandbox.