I'm building a simple React app where I have a pet with properties like hunger, boredom, and energy. I want to update these properties at different intervals (hunger every 5 seconds, boredom every 8 seconds, and energy every 10 seconds).
However, while the hunger stat updates correctly, the boredom and energy stats do not. I'm using setInterval
to update these values, but it seems like only hunger is being updated.
Here's the relevant code:
import { useEffect, useState } from "react";
import { Pet } from "./types/pet";
function App() {
const [pet, setPet] = useState<Pet | null>(null);
useEffect(() => {
// Load pet from localStorage or create a new pet
const savedPet = localStorage.getItem("pet");
if (savedPet) {
try {
const parsedPet = JSON.parse(savedPet) as Pet;
setPet(parsedPet);
} catch (error) {
console.error("Error parsing saved pet:", error);
createNewPet();
}
} else {
createNewPet();
}
}, []);
const updatePet = (updateFn: (currentPet: Pet) => Partial<Pet>) => {
setPet((prevPet) => {
if (!prevPet) return null;
const updatedPet = { ...prevPet, ...updateFn(prevPet) };
localStorage.setItem("pet", JSON.stringify(updatedPet));
return updatedPet;
});
};
useEffect(() => {
if (!pet) return;
const hungerInterval = setInterval(() => {
updatePet((pet) => ({ hunger: Math.min(pet.hunger + 1, 100) }));
}, 5000);
const boredomInterval = setInterval(() => {
updatePet((pet) => ({ boredom: Math.min(pet.boredom + 1, 100) }));
}, 8000);
const energyInterval = setInterval(() => {
updatePet((pet) => ({ energy: Math.max(pet.energy - 1, 0) }));
}, 10000);
return () => {
clearInterval(hungerInterval);
clearInterval(boredomInterval);
clearInterval(energyInterval);
};
}, [pet]);
return (
<div>
<p>Hunger: {pet.hunger}%</p>
<p>Boredom: {pet.boredom}%</p>
<p>Energy: {pet.energy}%</p>
</div>
);
}
export default App;
What I'm experiencing:
What I've tried:
Does anyone know why only the hunger stat is updating, and what I can do to fix this?
Each time you update pet (the first time would be in response to hunger changing, since that's the shortest interval), the useEffect is going to clear all of the intervals and reset them (and then the next one that triggers will be hunger again).
You want the useEffect only to run when a different pet is used, rather than whenever the current pet undergoes a stat change. So having [pet] in the dependency array is the problem. As @pmoleri stated, an id (or a name) that doesn't change per pet would be the way to go - [pet?.id]
or [pet?.name]
. If only one pet is supported in total, you can use an empty dependency array.