While working on my coding timer app ⏱️, I ran into a tricky bug:
Every time I completed a goal, the total coded time (awards) was getting saved twice.
The Problem 🐞
I had two useEffect
hooks:
- One for handling goal completion (🎉 alert, streak update, etc.)
- Another one for adding the session to total coded time.
Because I was setting goalCompleted = true
and resetting elapsed time in the same effect, the second useEffect
was firing again, causing a double save.
The Fix ✅
I moved the addToTotalCodedTime
call inside the goal completion effect itself and removed the extra effect.
This way, the award is saved once and only once.
// Before: two effects -> double saving
useEffect(() => {
if (goalTime && elapsedTime >= goalTime) {
setGoalCompleted(true);
setElapsedTime(0);
}
}, [elapsedTime, goalTime]);
useEffect(() => {
if (goalCompleted) {
addToTotalCodedTime(elapsedTime);
}
}, [goalCompleted]);
// After: single effect -> clean and safe
useEffect(() => {
if (goalTime && elapsedTime >= goalTime && !goalCompleted) {
alert("🎉 Congratulations! Goal complete.");
addToTotalCodedTime(elapsedTime); // ✅ Saved only once
setGoalCompleted(true);
setElapsedTime(0);
setIsRunning(false);
}
}, [elapsedTime, goalTime, goalCompleted]);
Takeaway 💡
Sometimes the simplest fix is not more code, but less code.
By consolidating logic into a single effect, I avoided race conditions and duplicate state updates.
📂 Full Project
Check out the repo here 👉 https://github.com/Usamaazeem03/the-time.git
Top comments (0)