You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中localStorage存储延迟求助:游戏每日游玩限制功能异常

问题

我正在实现一项数据存储至当日午夜的功能,核心需求:

  • 用户刷新页面后数据仍能保留
  • 用户完成游戏后需次日才能进行新一轮游玩

目前遇到存储延迟问题:处理当前输入时,localStorage存储的总是上一次输入的数据,相关代码如下:

const compareInput = useCallback((inputValue) => {
    const guess = PLAYERS.find(player => player.playerName.toLowerCase() === inputValue.toLowerCase());
    // console.log(guess);
    if(!guess) {
        alert("Player not found");
        return;
    }
    if(guess.jerseyNumber === hero[0].jerseyNumber) {
        setplayer1((prevValues) => ({...prevValues, jerseyNumber: guess.jerseyNumber}));
    }
    if(guess.jerseyNumber === hero[1].jerseyNumber) {
        setplayer2((prevValues) => ({...prevValues, jerseyNumber: guess.jerseyNumber}));
    }
    if(guess.jerseyNumber === hero[2].jerseyNumber) {
        setplayer3((prevValues) => ({...prevValues, jerseyNumber: guess.jerseyNumber}));
    }
    if(guess.jerseyNumber === hero[3].jerseyNumber) {
        setplayer4((prevValues) => ({...prevValues, jerseyNumber: guess.jerseyNumber}));
    }
    if(guess.franchise === hero[0].franchise) {
        setplayer1((prevValues) => ({...prevValues, franchise: guess.franchise}));
    }
    if(guess.franchise === hero[1].franchise) {
        setplayer2((prevValues) => ({...prevValues, franchise: guess.franchise}));
    }
    if(guess.franchise === hero[2].franchise) {
        setplayer3((prevValues) => ({...prevValues, franchise: guess.franchise}));
    }
    if(guess.franchise === hero[3].franchise) {
        setplayer4((prevValues) => ({...prevValues, franchise: guess.franchise}));
    }
    if(guess.playerName === hero[0].playerName) {
        setplayer1((prevValues) => ({...prevValues, playerName: guess.playerName}));
        setGuessPlayer1(true);
    }
    if(guess.playerName === hero[1].playerName) {
        setplayer2((prevValues) => ({...prevValues, playerName: guess.playerName}));
        setGuessPlayer2(true);
    }
    if(guess.playerName === hero[2].playerName) {
        setplayer3((prevValues) => ({...prevValues, playerName: guess.playerName}));
        setGuessPlayer3(true);
    }
    if(guess.playerName === hero[3].playerName) {
        setplayer4((prevValues) => ({...prevValues, playerName: guess.playerName}));
        setGuessPlayer4(true);
    }
    localStorage.setItem('player1', JSON.stringify(player1));
    localStorage.setItem('player2', JSON.stringify(player2));
    localStorage.setItem('player3', JSON.stringify(player3));
    localStorage.setItem('player4', JSON.stringify(player4));

}, [hero, inputValue, player1, player2, player3, player4]);
解决方案

问题根源

React的setState是异步操作,调用setplayer1这类方法后,player1的状态不会立即更新。你现在在调用setState后立刻执行localStorage.setItem,写入的自然是更新前的旧值,这就是存储延迟的原因。

修复方案

方案一:更新状态时同步写入localStorage

利用函数式更新的特性,在生成新状态的同时直接写入存储,确保存入的是最新值:

// 以更新player1的jerseyNumber为例
if(guess.jerseyNumber === hero[0].jerseyNumber) {
  setplayer1(prev => {
    const updatedPlayer1 = {...prev, jerseyNumber: guess.jerseyNumber};
    localStorage.setItem('player1', JSON.stringify(updatedPlayer1));
    return updatedPlayer1;
  });
}

对所有setplayerX的逻辑做同样修改,每个状态更新时同步写入对应的localStorage项。

方案二:用useEffect监听状态变化(更推荐)

移除compareInput里的localStorage写入代码,改用useEffect监听四个玩家状态的变化,状态更新时自动同步存储:

useEffect(() => {
  localStorage.setItem('player1', JSON.stringify(player1));
  localStorage.setItem('player2', JSON.stringify(player2));
  localStorage.setItem('player3', JSON.stringify(player3));
  localStorage.setItem('player4', JSON.stringify(player4));
}, [player1, player2, player3, player4]);

这种方式更简洁,也符合React处理副作用的最佳实践,避免在事件回调里混杂状态更新和存储操作。

当日午夜过期逻辑实现

针对“数据保留至当日午夜”的需求,可以在存储时额外记录当前日期,读取时校验日期是否过期:

// 存储数据时同时记录当前日期
const saveGameData = () => {
  const today = new Date().toDateString();
  localStorage.setItem('gameDate', today);
  // 写入玩家数据...
};

// 页面初始化时校验日期
useEffect(() => {
  const savedDate = localStorage.getItem('gameDate');
  const today = new Date().toDateString();
  
  if(savedDate !== today) {
    // 日期过期,重置所有游戏数据
    setplayer1(initialPlayerState);
    setplayer2(initialPlayerState);
    setplayer3(initialPlayerState);
    setplayer4(initialPlayerState);
    setGuessPlayer1(false);
    // ...重置其他游戏状态
    
    // 清除过期的存储数据
    localStorage.removeItem('player1');
    localStorage.removeItem('player2');
    localStorage.removeItem('player3');
    localStorage.removeItem('player4');
    localStorage.removeItem('gameDate');
  } else {
    // 读取已存储的玩家数据恢复状态
    const savedPlayer1 = JSON.parse(localStorage.getItem('player1'));
    if(savedPlayer1) setplayer1(savedPlayer1);
    // ...读取其他玩家数据
  }
}, []);

这样用户次日打开页面时,会自动重置游戏数据,满足“完成游戏后次日才能进行新一轮游玩”的要求。

内容的提问来源于stack exchange,提问作者user17031033

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:07:29