React(Vite) Todo应用本地正常线上报错:TypeError: t is not iterable
React(Vite) Todo应用线上部署后表单功能失效问题解决
问题概述
基于React(Vite)和useState开发的Todo应用,本地npm run dev运行正常,但线上部署后表单添加功能失效,控制台抛出TypeError: t is not iterable错误,经排查错误触发自addTodo函数调用。
报错信息
index-b568087f.js:61 Uncaught TypeError: t is not iterable at o (index-b568087f.js:61:377) at onClick (index-b568087f.js:61:798) at Object.Ld (index-b568087f.js:37:9855) at Ad (index-b568087f.js:37:10009) at Id (index-b568087f.js:37:10066) at Ds (index-b568087f.js:37:31459) at Rc (index-b568087f.js:37:31876) at index-b568087f.js:37:36788 at tc (index-b568087f.js:37:8967) at Yo (index-b568087f.js:37:33162)
代码问题分析
查看核心逻辑后定位问题:
- 初始化state时,线上首次访问无localStorage存储数据,
localStorage.getItem("list")返回null,经JSON.parse后localList为null,导致list初始状态为null。 - 渲染时用
list?.map规避了null的遍历问题,但addTodo函数中尝试解构展开null([...list, newTodo]),而null不属于可迭代类型,直接触发迭代错误。 - 本地环境因之前存储过数据,
localList为数组,因此未暴露该问题。
修复方案
1. 确保state初始值始终为数组
修改state初始化代码,当localList为null时兜底使用空数组,保证list类型始终为数组:
const localList = JSON.parse(localStorage.getItem("list")); // 用||兜底,保证list初始状态必为数组 const [list, setList] = useState(localList || []);
2. 优化setState为函数式更新(可选但更稳妥)
由于setState是异步操作,使用函数式更新可确保获取最新的state值,避免闭包导致的状态不一致:
const addTodo = (todo) => { const newTodo = { id: Math.random(), todo: todo, }; // 用trim简化空值判断,覆盖全空格场景 if (input.trim() !== "") { // 函数式更新,获取最新prevList setList(prevList => [...prevList, newTodo]); } setInput(""); };
3. 统一空值判断逻辑(可选)
将submitOnEnter中的空值判断改为trim(),统一代码逻辑:
const submitOnEnter = (e) => { e.preventDefault(); if (e.key === "Enter") { if (input.trim() === "") { return; } document.getElementById("addTask").click(); } };
验证效果
修改后重新部署线上环境,首次访问时list初始为空数组,点击添加按钮可正常创建Todo项,localStorage同步存储数据,无迭代错误抛出。
内容的提问来源于stack exchange,提问作者Noah Pittman
相关产品推荐
相关产品推荐

