React开发Tenzies游戏:localStorage读取状态值为undefined的问题
Tenzies游戏掷骰子次数存储问题修复方案
问题根源拆解
- prevRollCount状态冗余且逻辑错误:你初始化时把
prevRollCount设为rollCount的初始值0,之后每次掷骰子都同步让它加1,导致它和rollCount完全同步,根本存不了“上一次游戏的次数”。 - useEffect逻辑混乱:没有加依赖数组导致每次渲染都执行,而且
localStorage.setItem()返回的是undefined,你直接把这个结果传给setStoreRoll,所以刷新页面后storeRoll会立刻变成undefined。 - 状态更新时机冲突:获胜时的
storeRoll更新逻辑分散在useEffect和updateRollCount里,导致状态更新混乱,后续游戏还会累加次数。
修复步骤及代码调整
1. 简化状态定义
删掉多余的prevRollCount,只保留必要的状态:
const [tenzies, setTenzies] = useState(false); const [rollCount, setRollCount] = useState(0); // 初始化时从localStorage读取,没有数据则设为null const [storeRoll, setStoreRoll] = useState(() => { const saved = localStorage.getItem("die"); return saved ? JSON.parse(saved) : null; });
2. 正确使用useEffect处理存储
只在游戏获胜(tenzies变为true)时,把当前rollCount存入localStorage并更新storeRoll;组件初始化时已经读取过localStorage,不需要重复执行:
useEffect(() => { // 游戏获胜时,保存当前局的掷骰子次数 if (tenzies) { localStorage.setItem("die", JSON.stringify(rollCount)); setStoreRoll(rollCount); } }, [tenzies, rollCount]); // 仅当tenzies或rollCount变化时触发
3. 修正掷骰子和重置逻辑
rollDice只负责当前游戏的次数更新和骰子状态处理:
function rollDice() { if (!tenzies) { setDice((prevValue) => { return prevValue.map((die, index) => { return die.isHeld ? { ...die } : allNewDice([1, 2, 3, 4, 5, 6])[index]; }); }); // 未获胜时才增加次数,避免重置时额外加1 setRollCount(prev => prev + 1); } else { // 获胜后点击掷骰子,直接启动新游戏 setTenzies(false); setDice(allNewDice([1, 2, 3, 4, 5, 6])); setRollCount(0); setTime(0); } }
updateRollCount只需重置当前游戏的状态,存储逻辑交给useEffect处理:
function updateRollCount() { setTenzies(false); setDice(allNewDice([1, 2, 3, 4, 5, 6])); setRollCount(0); setTime(0); }
核心逻辑说明
- 游戏获胜时,
tenzies变为true,触发useEffect把当前局的rollCount存入localStorage,同时更新storeRoll用于展示“上一次的次数”。 - 新游戏启动后,
rollCount重置为0重新计数,不会和上一次的次数累加。 - 页面刷新时,
storeRoll初始化会直接读取localStorage里的历史数据,不会出现undefined的问题。
内容的提问来源于stack exchange,提问作者Hi - P
相关产品推荐
相关产品推荐

