React报错Error saving to hook array: object is not iterable
问题描述
实现点击商品按钮将商品对象存入React Hook管理的数组功能时,持续触发Error saving to hook array: object is not iterable报错。
初始实现代码
let shoppingArray = []; const shopping = (item) => { shoppingArray.push(item); console.log(shoppingArray); setShoppingBag(...shoppingBag, shoppingArray); }; ... <ShoppingCartOutlinedIcon className="icons" onClick={() => shopping(item)}></ShoppingCartOutlinedIcon>
控制台报错信息
Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))

调整后仍失效的代码
将代码修改为如下写法后功能依然无法正常运行:
const [shoppingBag, setShoppingBag] = React.useState([]); const shopping = (item) => { setShoppingBag(...shoppingBag, item); };
错误原因
- 核心错误:
useState返回的状态更新函数setShoppingBag仅接收1个参数,参数为新的状态值,或返回新状态值的回调函数。两次错误写法都对setShoppingBag传入了多个展开后的参数,React只会识别第一个参数作为新状态,也就是原shoppingBag数组的第一个元素(非数组类型),后续参数直接被忽略。当后续渲染再次尝试对非数组类型的值做展开操作时,就会触发「对象不可迭代」的报错。 - 第一版代码额外问题:
- 在组件外部额外声明
shoppingArray存储数据,组件重渲染时该变量不会被重置,会引发状态污染 - 传入整个
shoppingArray作为参数,会导致数组嵌套存入状态,不符合追加单个商品的预期
- 在组件外部额外声明
正确实现方案
基础写法
直接将拼接完成的新数组作为唯一参数传入更新函数:
const [shoppingBag, setShoppingBag] = React.useState([]); const shopping = (item) => { setShoppingBag([...shoppingBag, item]); };
推荐写法(函数式更新)
如果短时间内多次触发添加操作,直接读取外层的shoppingBag可能拿到闭包缓存的旧值,使用函数式更新可以保证始终基于最新状态计算:
const [shoppingBag, setShoppingBag] = React.useState([]); const shopping = (item) => { setShoppingBag(prevShoppingBag => [...prevShoppingBag, item]); };
内容的提问来源于stack exchange,提问作者Captai-N
相关产品推荐
相关产品推荐

