如何在条件下操作LocalStorage并解决Tenzies游戏计时显示异常
解决Tenzies游戏LocalStorage读写及UI展示问题
问题1:fetchPrevioustime多次执行
原因:直接将fetchPrevioustime()作为useState初始值时,组件每次渲染都会调用该函数。useState的函数式初始值写法才能保证仅在组件首次挂载时执行一次。
解决:
修改state初始化逻辑,改用函数式初始化:
const [recordTime, setRecordTime] = useState(() => fetchPreviousTime())
同时修正fetchPreviousTime的返回结构,确保统一:
function fetchPreviousTime() { const storedRecord = localStorage.getItem("recordTime"); // 有记录则解析返回,无记录则返回默认最大时间(方便后续比较) if (storedRecord) { return JSON.parse(storedRecord); } return { mn: "99", sc: "59" }; }
问题2:recordTime.sc展示为空
原因:
- 数据结构混乱:获胜时存储数组
[{mn, sc}],初始化时返回嵌套对象{recordedTime: 数组},导致recordTime结构时而为数组、时而为对象,无法稳定读取.sc属性。 - 未处理无历史记录的边界情况,初始值可能为
undefined,读取属性会报错或为空。
解决:
步骤1:统一存储结构并加入时间比较逻辑
将存储格式改为单个时间对象,同时仅在当前耗时更短时更新记录:
useEffect(() => { if (tenzies) { // 转换为总秒数方便比较 const currentTotalSeconds = parseInt(mn) * 60 + parseInt(sc); const recordTotalSeconds = parseInt(recordTime.mn) * 60 + parseInt(recordTime.sc); if (currentTotalSeconds < recordTotalSeconds) { const newRecord = { mn, sc }; localStorage.setItem("recordTime", JSON.stringify(newRecord)); setRecordTime(newRecord); } } }, [tenzies, mn, sc, recordTime]);
步骤2:修正UI展示逻辑
现在recordTime始终是包含mn和sc的对象,直接读取即可,同时添加无记录的友好提示:
<div className="congrats" style={stylesWon}> Congrats! You have won the game. <br></br> You took {mn > 0 && `${mn} minutes and `} {sc} seconds. Your best time is {recordTime.mn !== "99" ? `${recordTime.mn}m ${recordTime.sc}s` : "暂无记录"} </div>
完整关键代码总结
- 初始化state:
const [recordTime, setRecordTime] = useState(() => fetchPreviousTime()); function fetchPreviousTime() { const storedRecord = localStorage.getItem("recordTime"); return storedRecord ? JSON.parse(storedRecord) : { mn: "99", sc: "59" }; }
- 获胜时的更新逻辑:
useEffect(() => { if (tenzies) { const currentTotal = parseInt(mn) * 60 + parseInt(sc); const recordTotal = parseInt(recordTime.mn) * 60 + parseInt(recordTime.sc); if (currentTotal < recordTotal) { const newRecord = { mn, sc }; localStorage.setItem("recordTime", JSON.stringify(newRecord)); setRecordTime(newRecord); } } }, [tenzies, mn, sc, recordTime]);
- UI展示:
<div className="congrats" style={stylesWon}> Congrats! You have won the game. <br></br> You took {mn > 0 && `${mn} minutes and `} {sc} seconds. Your best time is {recordTime.mn !== "99" ? `${recordTime.mn}m ${recordTime.sc}s` : "暂无记录"} </div>
内容的提问来源于stack exchange,提问作者nikita jd
相关产品推荐
相关产品推荐

