'RequestAnimationFrame so lag when update the millisecond time ONLY first time
I just want to create the tap-game. find the fastest time for tap 100 images.
The first, I fetch 50 images from my API. each image size about 3-4mb.
After that I use RequestAnimationFrame for count the time. and I do not know why in the fast time I click. millisecond timer so laggy when I click the image. But after game end and click try again button. the timer will be normally.
Is it about size of image is so big ? if it is related, I want to know why after the first time it normally.
Could someone explain me why. And How can I fix it?
I use React and here is my code
import { useState, useEffect, useRef } from "react";
import "./App.css";
const Hidden = () => {
const [loading, setLoading] = useState(true);
const [start, setStart] = useState(false);
const [end, setEnd] = useState(false);
const [state, setState] = useState({
images: [],
current: 0,
});
const [timer, setTimer] = useState(0);
const intervalRef = useRef();
useEffect(() => {
const fetchData = async () => {
const x = [...new Array(50)].map(
async (x, i) =>
await fetch(`http://localhost:1234/images/${i}.png`)
);
const result = await Promise.all(x);
const blobs = await Promise.all(result.map(async (x) => await x.blob()));
const objUrl = blobs.map((x) => URL.createObjectURL(x));
return objUrl;
};
const constructImage = async () => {
const newImages = await fetchData();
setState((prev) => ({ ...prev, images: newImages }));
setLoading(false);
};
constructImage();
}, []);
useEffect(() => {
if (start) {
const startTime = Date.now();
function timer() {
intervalRef.current = requestAnimationFrame(timer);
const elapsedTime = Date.now() - startTime;
const formatTime = (elapsedTime / 1000).toFixed(3);
setTimer(formatTime);
}
intervalRef.current = requestAnimationFrame(timer);
}
return () => cancelAnimationFrame(intervalRef.current);
}, [start]);
useEffect(() => {
if (state.images.length > 0)
if (state.current === state.images.length) setEnd(true);
}, [state.current]);
const nextImage = () => {
if (!start) setStart(true);
if (state.current === state.images.length - 1) setStart(false);
setState((prev) => ({ ...prev, current: prev.current + 1 }));
};
const reset = () => {
setStart(false);
setEnd(false);
setState((prev) => ({ ...prev, current: 0 }));
setTimer(0);
intervalRef.current = null;
};
return (
<div className="App">
<header className="App-header">
{loading && <div>Loading ....</div>}
<>
{!loading && !end && state.current + 1}
{end && (
<div>
<h1>End!</h1>
<h3>time: {timer}</h3>
<button onClick={reset}>try again</button>
</div>
)}
{!loading &&
state.images.map((image, i) => (
<img
key={i}
src={image}
alt={i}
style={{
display: i === state.current ? "block" : "none",
width: "20rem",
}}
onClick={nextImage}
/>
))}
{!loading && !end && <span>{timer}</span>}
</>
</header>
</div>
);
};
export default Hidden;
and example is here https://l9wyqz.csb.app/
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
