admin管理员组文章数量:1401193
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:
- The hunger stat updates correctly every 5 seconds.
- The boredom and energy stats do not update as expected, even though their intervals are set up in the same way.
What I've tried:
- I've checked the intervals and they seem to be correct.
- I tried updating the state with functional updates to ensure the latest state is used, but still, only hunger updates.
Does anyone know why only the hunger stat is updating, and what I can do to fix this?
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:
- The hunger stat updates correctly every 5 seconds.
- The boredom and energy stats do not update as expected, even though their intervals are set up in the same way.
What I've tried:
- I've checked the intervals and they seem to be correct.
- I tried updating the state with functional updates to ensure the latest state is used, but still, only hunger updates.
Does anyone know why only the hunger stat is updating, and what I can do to fix this?
Share Improve this question asked Mar 24 at 17:08 IzaanIzaan 1354 bronze badges 8- 4 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). – James Commented Mar 24 at 17:22
- "I've checked the intervals and they seem to be correct." - are they? How did you check? Do the callbacks run at the expected times? – Bergi Commented Mar 24 at 17:30
- 1 If you have an "id" maybe use [pet?.id] as the effect dependency. – pmoleri Commented Mar 24 at 17:30
- 1 @James Please make that an answer – Bergi Commented Mar 24 at 17:31
- 2 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]). Or, if only one pet is supported in total, use an empty dependency array. – James Commented Mar 24 at 17:41
2 Answers
Reset to default 3Each 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.
You're updating the pet object, but you also say pet is a dependency of the useEffect
You should do like this to only register all your interval once, and inside them, you check if the pet is existing or not
useEffect(() => {
const hungerInterval = setInterval(() => {
if (!pet) return;
updatePet((pet) => ({ hunger: Math.min(pet.hunger + 1, 100) }));
}, 5000);
const boredomInterval = setInterval(() => {
if (!pet) return;
updatePet((pet) => ({ boredom: Math.min(pet.boredom + 1, 100) }));
}, 8000);
const energyInterval = setInterval(() => {
if (!pet) return;
updatePet((pet) => ({ energy: Math.max(pet.energy - 1, 0) }));
}, 10000);
return () => {
clearInterval(hungerInterval);
clearInterval(boredomInterval);
clearInterval(energyInterval);
};
}, []);
It would even allow you to remove the pet existence check, and merge both of your useEffect
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 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);
};
}, []);
本文标签:
版权声明:本文标题:javascript - Why is my pet state only updating hunger in React, and not boredom or energy? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744238184a2596656.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论