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

React待办应用部署Netlify报JSON Unexpected token u解析错误

问题根因
  • 核心bug在getTodoFromLocal函数的返回逻辑缺失:
    1. 线上首次访问时浏览器无历史localStorage数据,函数判断localStorage.getItem("todos") === null的分支,只执行了往存储写入空数组的操作,没有写return语句,函数默认返回undefined
    2. useState(getTodoFromLocal())拿到undefined作为todos初始值后,立刻触发依赖todos的useEffect执行saveToLocal:此时JSON.stringify(undefined)返回undefined,转成字符串存入localStorage的值就是"undefined"
    3. 后续读取存储时,JSON.parse("undefined")就会抛出Unexpected token u in JSON at position 0错误——字符串首字符是u,不属于合法JSON格式
  • 两个隐藏逻辑漏洞:
    • try/catch块捕获解析错误后仅打印日志,没有返回兜底空数组,依然会返回undefined
    • 首次加载时写的useEffect(() => { getTodoFromLocal(); }, [])完全无效,函数返回值没有被用来更新todos状态
  • 本地运行正常是因为开发阶段浏览器已经存过合法的todos数组数据,一直走else分支正常解析返回,不会触发if分支无返回的bug;线上部署后是全新访问域名,无历史存储数据,直接触发逻辑漏洞。
修复方案

只需要修改App.js的相关逻辑即可,其余组件无需改动:

  1. 重写getTodoFromLocal函数,保证所有分支都明确返回数组类型,增加多层兜底
  2. 删除无效的首次加载useEffect调用
  3. 给存储写入逻辑增加类型校验,避免异常值写入localStorage

修改后的核心代码如下:

// get data from local
const getTodoFromLocal = () => {
  try {
    const localTodo = localStorage.getItem("todos");
    // 无存储值时初始化存储并返回空数组
    if (localTodo === null) {
      localStorage.setItem("todos", JSON.stringify([]));
      return [];
    }
    const parsedTodo = JSON.parse(localTodo);
    // 兜底:解析结果非数组时返回空数组,避免后续map执行报错
    return Array.isArray(parsedTodo) ? parsedTodo : [];
  } catch (error) {
    console.log("本地存储解析失败,已重置:", error);
    // 解析出错时清空异常存储值,返回空数组
    localStorage.setItem("todos", JSON.stringify([]));
    return [];
  }
}

const App = () => {
  // states
  const [inputText, setInputText] = useState("");
  const [todos, setTodos] = useState(getTodoFromLocal());
  const [status, setStatus] = useState("all");
  const [filteredTodo, setFilteredTodo] = useState([]);

  // 删除以下无效的useEffect代码
  // useEffect(() => {
  //   getTodoFromLocal();
  // }, [])

  // 页面加载、todos或status变化时执行过滤和存储
  useEffect(() => {
    filterHandler();
    saveToLocal();
  }, [todos, status])

  // functions
  const filterHandler = () =>{
    switch (status) {
      case 'completed':
       setFilteredTodo(todos.filter(todo => todo.completed === true));
       break;
      case 'incompleted':
        setFilteredTodo(todos.filter(todo => todo.completed === false));
        break;
      default:
        setFilteredTodo(todos);
        break;
    }
  }

  // 保存数据到本地存储
  const saveToLocal = () => {
    // 仅当todos是数组时才写入存储,避免异常值污染
    if (Array.isArray(todos)) {
      localStorage.setItem("todos", JSON.stringify(todos));
    }
  };

  // 其余return渲染逻辑保持不变即可
}

修改完成后重新部署到Netlify,首次访问会自动初始化空的待办列表,刷新页面数据持久化正常,不会再出现JSON解析报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:15:45