React Native中AsyncStorage mergeItem数组对象不兼容报错排查
Hey,我来帮你拆解这个问题——你遇到的mergeItem失败本质是两个问题叠加:代码里的变量名错误,加上mergeItem本身不支持数组结构的存储。咱们一步步来搞定它:
问题核心原因
首先看你的报错信息:
[Unhandled promise rejection: Error: Value [{"test":{"title":"test","subThings":[]}},{"test2":{"title":"test2","subThings":[]}}] of type org.json.JSONArray cannot be converted to JSONObject]
这个报错直接点出了关键:AsyncStorage里实际存储的是数组,但mergeItem方法只能处理JSON对象的合并——它会默认把存储值解析成对象,遇到数组自然就报错了。
再看你代码里的变量问题,这也是导致逻辑混乱的源头:
- 第一个
.then()里写了JSON.parse(decks),但decks这个变量根本没定义!这里应该是JSON.parse(things)(也就是AsyncStorage.getItem返回的存储值)。 - 第一个
.then()最后return { decks, subThings }里的decks同样是无中生有,应该改成return { storedThings: things, subThings }(换个变量名避免遮蔽外层的things)。 - 外层定义的
let things = {}完全没用,因为.then()里的参数things已经把它遮蔽了,后续代码里的JSON.parse(things)根本拿不到正确的存储值。
解决方案(适配现有数组存储结构)
既然你无法修改现有的数组存储结构,那咱们就放弃mergeItem,改用「获取数组→修改数组→重新存储」的流程,下面是修正后的代码:
const arrToObj = (array) => array.reduce((obj, item) => { obj[Object.keys(item)[0]] = Object.values(item)[0] return obj }, {}) export const addThingToThing = async (title, subThing) => { // 修正参数名,和内部使用的subThing统一 try { // 1. 获取存储的原始数组数据 const storedThingsStr = await AsyncStorage.getItem(THINGS_STORAGE_KEY); if (!storedThingsStr) { console.log("No existing things stored"); return; } const storedThingsArray = JSON.parse(storedThingsStr); // 2. 遍历数组,找到对应title的项并更新subThings const updatedThingsArray = storedThingsArray.map(item => { const itemKey = Object.keys(item)[0]; if (itemKey === title) { // 复制原对象,避免直接修改原数据 return { [itemKey]: { ...item[itemKey], subThings: [...item[itemKey].subThings, subThing] } }; } // 其他项保持不变 return item; }); // 3. 把修改后的数组重新存回AsyncStorage await AsyncStorage.setItem(THINGS_STORAGE_KEY, JSON.stringify(updatedThingsArray)); console.log("Thing added successfully!"); } catch (error) { console.log(`Error adding thing to thing: ${error.message}`); } }
改动说明:
- 改用
async/await的同步写法,避免.then()嵌套导致的变量遮蔽问题,代码逻辑更清晰。 - 直接操作存储的数组:遍历找到对应title的项,通过复制对象的方式更新
subThings,避免修改原数组的副作用。 - 增加了空值判断,防止存储为空时的JSON解析错误。
- 修正了参数名不一致的问题(原代码函数参数是
thing,但内部用的是subThing)。
关于打印对象但存储是数组的困惑
你打印的obj是自己把数组转成对象后的临时结果,但因为原代码逻辑错误,根本没正确读取到存储的数组,导致你看到的打印值和实际存储值不一致——修正后的代码会直接操作原始数组,就能解决这个认知偏差啦。
内容的提问来源于stack exchange,提问作者geoffjay
相关产品推荐
相关产品推荐

