I am developing a mining application using React where a timer should increment the user’s coins every second. However, the timer is adding coins at an incredibly fast rate (every nanosecond) instead of every second.
Here is the code I am using in my useEffect hook:
<code> const userDocRef = doc(db, 'users', user.id); // Adjust the path to your Firestore collection
await setDoc(userDocRef, data, { merge: true });
const fetchUserState = async () => {
if (user && !user.anotherStart) {
const userDocRef = doc(db, 'users', user.id);
const userDoc = await getDoc(userDocRef);
const userData = userDoc.data();
const elapsedTime = Math.floor((Date.now() - userData.startTime) / 1000);
const remainingTime = userData.countdown - elapsedTime;
// Start countdown if necessary
if (elapsedTime >= userData.countdown) {
await updateUserInFirestore({ isSpinning: false });
setCoins(user.countdown);
setShowClaimButton(true); // Show claim button if countdown is completed
startCountdown(remainingTime);
console.error('Error fetching user state:', error);
// Perform initial fetch only once when user.isSpinning is true
if (user && user.isSpinning) {
}, [user, startCountdown]);
<code> const userDocRef = doc(db, 'users', user.id); // Adjust the path to your Firestore collection
await setDoc(userDocRef, data, { merge: true });
};
useEffect(() => {
const fetchUserState = async () => {
if (user && !user.anotherStart) {
toggleSpin();
const userDocRef = doc(db, 'users', user.id);
try {
const userDoc = await getDoc(userDocRef);
if (userDoc.exists()) {
const userData = userDoc.data();
setUser((prevUser) => ({
...prevUser,
...userData
}));
const elapsedTime = Math.floor((Date.now() - userData.startTime) / 1000);
const remainingTime = userData.countdown - elapsedTime;
// Start countdown if necessary
if (elapsedTime >= userData.countdown) {
await updateUserInFirestore({ isSpinning: false });
setCoins(user.countdown);
setShowClaimButton(true); // Show claim button if countdown is completed
setIsSpinning(false);
setTimer(null);
} else {
startCountdown(remainingTime);
}
}
} catch (error) {
console.error('Error fetching user state:', error);
}
}
};
// Perform initial fetch only once when user.isSpinning is true
if (user && user.isSpinning) {
fetchUserState();
}
}, [user, startCountdown]);
</code>
const userDocRef = doc(db, 'users', user.id); // Adjust the path to your Firestore collection
await setDoc(userDocRef, data, { merge: true });
};
useEffect(() => {
const fetchUserState = async () => {
if (user && !user.anotherStart) {
toggleSpin();
const userDocRef = doc(db, 'users', user.id);
try {
const userDoc = await getDoc(userDocRef);
if (userDoc.exists()) {
const userData = userDoc.data();
setUser((prevUser) => ({
...prevUser,
...userData
}));
const elapsedTime = Math.floor((Date.now() - userData.startTime) / 1000);
const remainingTime = userData.countdown - elapsedTime;
// Start countdown if necessary
if (elapsedTime >= userData.countdown) {
await updateUserInFirestore({ isSpinning: false });
setCoins(user.countdown);
setShowClaimButton(true); // Show claim button if countdown is completed
setIsSpinning(false);
setTimer(null);
} else {
startCountdown(remainingTime);
}
}
} catch (error) {
console.error('Error fetching user state:', error);
}
}
};
// Perform initial fetch only once when user.isSpinning is true
if (user && user.isSpinning) {
fetchUserState();
}
}, [user, startCountdown]);
Here is startCountdown:
<code> const startCountdown = (initialTime) => {
let timeLeft = initialTime;
setTimer(formatTime(timeLeft));
countdownRef.current = setInterval(() => {
setCoins((prev) => prev + user.speed); // Increment coins based on user speed
setProgress(((initialTime - timeLeft) / initialTime) * 100);
setTimer(formatTime(timeLeft));
clearInterval(countdownRef.current);
setShowClaimButton(true);
updateUserInFirestore({ isSpinning: false, coins: coins + user.speed, progress: 100 });
<code> const startCountdown = (initialTime) => {
let timeLeft = initialTime;
setTimer(formatTime(timeLeft));
countdownRef.current = setInterval(() => {
setCoins((prev) => prev + user.speed); // Increment coins based on user speed
timeLeft -= 1;
setProgress(((initialTime - timeLeft) / initialTime) * 100);
setTimer(formatTime(timeLeft));
if (timeLeft <= 0) {
clearInterval(countdownRef.current);
setIsSpinning(false);
setTimer(null);
setShowClaimButton(true);
updateUserInFirestore({ isSpinning: false, coins: coins + user.speed, progress: 100 });
}
}, 1000);
};
</code>
const startCountdown = (initialTime) => {
let timeLeft = initialTime;
setTimer(formatTime(timeLeft));
countdownRef.current = setInterval(() => {
setCoins((prev) => prev + user.speed); // Increment coins based on user speed
timeLeft -= 1;
setProgress(((initialTime - timeLeft) / initialTime) * 100);
setTimer(formatTime(timeLeft));
if (timeLeft <= 0) {
clearInterval(countdownRef.current);
setIsSpinning(false);
setTimer(null);
setShowClaimButton(true);
updateUserInFirestore({ isSpinning: false, coins: coins + user.speed, progress: 100 });
}
}, 1000);
};
For toggleSpin:
<code> const coinElement = coinRef.current;
coinElement.classList.toggle('spin');
setIsSpinning(!isSpinning);
setSpinSpeed((prevSpeed) => Math.min(prevSpeed + user.speed, 10)); // Increase speed
<code> const coinElement = coinRef.current;
if (coinElement) {
coinElement.classList.toggle('spin');
}
setIsSpinning(!isSpinning);
setSpinSpeed((prevSpeed) => Math.min(prevSpeed + user.speed, 10)); // Increase speed
};
</code>
const coinElement = coinRef.current;
if (coinElement) {
coinElement.classList.toggle('spin');
}
setIsSpinning(!isSpinning);
setSpinSpeed((prevSpeed) => Math.min(prevSpeed + user.speed, 10)); // Increase speed
};
Please review and help, i have tried many logics but none works. I want the increment to be in every seconds, i have set the timer to 1000, i dont know if it is the useEffect causing it to behave that way. I added clearInterval to avoid memory leaks but it preventing the timer to show it ticking in real-time. Thank you!