React/Redux项目中无法删除Firestore文档的报错问题求助
Redux Toolkit 结合 Firestore 实现CRUD时文档删除功能报错
问题现象
- 基于Redux Toolkit与Firestore搭建CRUD应用过程中,Firestore文档删除功能始终无法正常运行,多次调整实现方式后仍未定位失效原因
- 运行时抛出固定错误信息:
Cannot use 'in' operator to search for '_delegate' in undefined
- 已尝试的排查操作:
- 传入硬编码测试数据触发删除函数,问题未解决
- 移除
DELETE_RECIPEreducer后运行代码,故障依然存在 - 最初判断QuerySnapshot自带的forEach方法支持async/await写法,因此未使用
createAsyncThunk,不确定该判断是否存在错误
问题关联代码
Slice 层实现
export const recipeSlice = createSlice({ name: 'recipesSlice', initialState: { recipes: [] }, reducers: { ADD_RECIPE: (state, action) => { state.recipes.push(action.payload) }, DELETE_RECIPE: (state, action) => { state.recipes = state.recipes.filter((recipe) => recipe.recipeId !== action.payload.recipeId) } } })
自定义删除Thunk实现
export const deleteRecipe = ({recipeId}) => { return async (dispatch) => { const q = query(collection(db, "recipes"), where("recipeId", "==", `${recipeId}`)); const querySnapshot = await getDocs(q); querySnapshot.forEach(async(doc) => { console.log(doc.id, " => ", doc.data()) await deleteDoc(doc) }); dispatch(DELETE_RECIPE({recipeId})) } }
故障根因
- 核心报错诱因:
deleteDoc()方法要求入参必须是DocumentReference类型的文档引用对象,当前代码直接传入遍历得到的doc(QueryDocumentSnapshot快照实例),Firestore SDK内部尝试读取引用对象内置的_delegate属性时拿到undefined,直接抛出类型错误。 - 隐藏逻辑缺陷:
querySnapshot.forEach()本质是同步遍历方法,即使是Firestore官方提供的遍历API,也不会等待内部异步回调的Promise执行,会直接执行后续dispatch逻辑,导致远端删除操作和本地Redux状态更新时序错乱。 - 潜在代码风险:若未手动将slice对应reducer的action creator解构赋值为
DELETE_RECIPE变量,直接调用DELETE_RECIPE()会触发未定义错误,标准调用方式为recipeSlice.actions.DELETE_RECIPE。
修复方案
替换原有删除thunk逻辑为以下实现即可:
export const deleteRecipe = ({recipeId}) => { return async (dispatch) => { // 移除不必要的模板字符串转义 const q = query(collection(db, "recipes"), where("recipeId", "==", recipeId)); const querySnapshot = await getDocs(q); const deleteTasks = [] querySnapshot.forEach((doc) => { console.log(doc.id, " => ", doc.data()) // 传入快照挂载的ref属性(即对应文档的引用对象)作为deleteDoc入参 deleteTasks.push(deleteDoc(doc.ref)) }); // 等待所有远端删除操作完成 await Promise.all(deleteTasks) // 再更新本地Redux状态,保证数据一致性 dispatch(recipeSlice.actions.DELETE_RECIPE({recipeId})) } }
补充说明
- 该业务场景不需要强制使用
createAsyncThunk,自定义thunk的写法完全适用,之前的判断没有错误。 - 硬编码ID测试仍报错、移除本地reducer仍报错的核心原因是错误发生在Firestore SDK调用阶段,代码还未执行到dispatch逻辑,和入参值、本地reducer逻辑无关。
内容的提问来源于stack exchange,提问作者JordanK
相关产品推荐
相关产品推荐

