我正在构建一个简单的 React 应用,其中有一只宠物,它有饥饿、无聊和精力等属性。我想以不同的间隔更新这些属性(每 5 秒更新一次饥饿,每 8 秒更新一次无聊,每 10 秒更新一次精力)。
但是,虽然饥饿值可以正确更新,但无聊值和精力值却不能。我曾经setInterval
更新过这些值,但似乎只有饥饿值在更新。
相关代码如下:
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;
我的经历:
- 饥饿值每 5 秒正确更新一次。
- 尽管无聊和能量统计数据的间隔设置方式相同,但它们并没有按预期更新。
我尝试过的:
- 我已检查过间隔并且它们似乎是正确的。
- 我尝试使用功能更新来更新状态以确保使用最新状态,但仍然只有饥饿更新。
有人知道为什么只有饥饿状态在更新,以及我该怎么做才能解决这个问题?
每次更新宠物时(第一次是为了响应饥饿变化,因为这是最短的间隔),useEffect 都会清除所有间隔并重置它们(然后下一个触发的间隔将再次是饥饿)。
您希望 useEffect 仅在使用其他宠物时运行,而不是在当前宠物发生状态变化时运行。因此,依赖项数组中包含 [pet] 是个问题。正如 @pmoleri 所说,每个宠物不变的 id(或名称)是可行的方法 -
[pet?.id]
或者[pet?.name]
。如果总共只支持一只宠物,则可以使用空的依赖项数组。您正在更新 pet 对象,但您还说 pet 是 useEffect 的依赖项
你应该这样做,只注册一次所有的间隔,并在其中检查宠物是否存在
它甚至允许您删除宠物存在检查,并合并您的 useEffect