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

React重启后useState仅加载localStorage最后一条用户数据排查

问题根因

异常完全出在App.js中读取localStorage的useEffect逻辑,属于React状态更新的经典闭包问题:

  • 该useEffect依赖数组为空,仅在组件首次挂载时执行1次,回调函数内捕获的users变量永远是组件初始化时的3个内置测试用户数组,不会拿到后续状态更新后的值。
  • 你在for循环内每读取一个localStorage中的用户,就执行一次setUsers([...users, parsedUser])。由于每次调用时拿到的users都是初始的3个测试用户数组,相当于每次更新都是「初始3个用户 + 当前遍历到的单个用户」,之前遍历读到的用户根本没有被累加进状态。
  • 循环结束后,最后一次setUsers的执行结果会覆盖前面所有更新,最终users状态就只剩初始3个测试用户 + localStorage中最后一个注册的用户,其余注册用户全部丢失,自然会触发“Uncorrect email”报错。
  • 额外隐患:当前写法直接遍历localStorage所有key,会把localStorage中存储的其他非用户数据也解析后塞入用户列表,后续容易引发其他异常。
修复代码

把原有useEffect替换为如下逻辑即可:

useEffect(() => {
  const loadedUsers = [];
  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    const rawValue = localStorage.getItem(key);
    try {
      const parsed = JSON.parse(rawValue);
      // 简单校验是否为合法用户数据,过滤无关存储项
      if (parsed?.email && parsed?.password) {
        loadedUsers.push(parsed);
      }
    } catch {
      // 跳过非JSON格式的无关存储项
      continue;
    }
  }
  // 用函数式状态更新拿到最新的前置状态,一次性拼接所有加载到的用户,仅触发一次状态更新
  setUsers(prevUsers => [...prevUsers, ...loadedUsers]);
}, []);
优化建议

更合理的存储方式是不要把每个用户单独存为localStorage的独立key,而是将整个用户数组序列化后存在单个固定key(例如app_registered_users)下:

  • 注册新用户时,先读取该key下的全量用户数组,追加新用户后整体序列化存回
  • 应用初始化时,仅读取这一个固定key即可拿到所有注册用户,不需要遍历整个localStorage,从根源上避免读入无关数据、循环更新状态的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:06:09