如何从Action Creator无错误调度到Reducer?Firebase图片上传报错解决
你碰到的这个情况挺典型的:图片明明成功传到Firebase Storage和Firestore了,但流程走完偏要抛出一个“Invalid attempt to spread non-iterable instance”的错误,控制台先输出1、2、3、4,显示上传成功,紧接着就蹦出错误。你说清除Storage里的重复测试数据后问题暂时解决了,但这只是绕开了表面现象,咱们得从代码逻辑里揪出根本原因,彻底搞定它。
错误到底出在哪?
这个报错的核心是你在Reducer里尝试对一个非可迭代的对象用扩展运算符(...)。看你Reducer里的这段代码:
case UPLOAD_SUCCESS: console.log('succesa girdi'); return { ...state, data: [...state.data, payload], loading: false }
当state.data不是数组的时候,[...state.data]就会直接炸锅。那state.data怎么会不是数组呢?
你的初始状态INITIAL_STATE里data确实是空数组[],但看UPLOAD_START的处理逻辑:
case UPLOAD_START: return { ...state, data: payload, loading: true }
而你在Action Creator里触发UPLOAD_START的时候,根本没传payload:
dispatch({ type: UPLOAD_START }); // 这里没有payload参数
这就导致state.data被设置成了undefined!等到后续执行UPLOAD_SUCCESS时,[...state.data, payload]就是在对undefined做扩展操作,自然抛出“非可迭代实例”的错误。
至于清除测试数据后问题消失,大概率是之前重复测试时,GET_PHOTOS_SUCCESS把state.data重置成了数组,暂时掩盖了UPLOAD_START的bug,但代码逻辑的问题还在,下次说不定又会触发。
代码修复方案
1. 修正UPLOAD_START的Reducer逻辑
UPLOAD_START只需要标记“正在加载”,完全不需要修改data字段,保持原有数据即可:
case UPLOAD_START: return { ...state, loading: true } // 删除data: payload这一行
2. 清理其他不必要的data赋值
看你的Reducer里,UPLOAD_FAILED、GET_PHOTOS_START这些case都直接把data设为payload,但很多场景下这些动作不需要更新数据列表:
UPLOAD_FAILED:只需要把loading设为false,没必要覆盖data(除非你要展示错误相关的数据)GET_PHOTOS_START:同理,只需要标记加载状态,不要修改data
调整后示例:
case UPLOAD_FAILED: return { ...state, loading: false } case GET_PHOTOS_START: return { ...state, loading: true }
3. 优化Action Creator里的冗余代码
你Action Creator里的await dispatch({ type: UPLOAD_SUCCESS, payload: snapshot.downloadURL })其实没必要加await,因为dispatch是同步操作,直接调用就行:
dispatch({ type: UPLOAD_SUCCESS, payload: snapshot.downloadURL });
最后总结
你之前清除测试数据的方法只是临时救急,真正的问题是Reducer里UPLOAD_START错误地把data设成了undefined,导致后续扩展数组时出错。按照上面的步骤修正代码后,就能彻底解决这个问题,不用再依赖清除测试数据这种临时方案啦。
内容的提问来源于stack exchange,提问作者Çağatay Sert

