Next.js/React中Firebase/Firestore首次调用Async Await失效问题
问题:批量更新Firestore文档时首次点击无效果,需二次触发
问题场景
给题库题目添加「考试机构」「年份」分类,流程为:用户选择题目与分类字段后,先检查Firestore文档字段是否存在或已包含目标分类,生成两个待更新数组,再执行批量更新。但首次调用validateData()时,生成的EITemp和YRTemp为空数组,需点击两次按钮才能获取正确数据并完成更新。
核心原因
React的状态更新(setEI、setYR)是异步操作,调用setEI(EITemp)后立刻访问EI变量,拿到的仍是更新前的旧值。导致首次执行saveData()时,使用的是空数组,没有实际更新操作;第二次点击时,状态已完成更新,才能获取到正确的待更新文档ID。
解决方案
跳过异步状态更新的依赖,直接将生成的临时数组作为参数传递给saveData(),避免等待状态更新的延迟。
修改后的代码
1. 重构saveData函数,接收待更新文档ID数组参数
const saveData = async (eiDocs, yrDocs) => { const batch = writeBatch(firestore); const EIValue = selectedFields.examInstitute; const YRValue = selectedFields.year; // 处理考试机构分类更新 if (eiDocs.length > 0) { const uniqueDocs = Array.from(new Set(eiDocs)); uniqueDocs.forEach(docID => { const docRef = doc(firestore, "multichoice", docID); // 合并update操作,减少批量任务数量 batch.update(docRef, { ["ExamInstitute"]: arrayUnion(EIValue), ["Updated"]: timestamp }); }); } // 处理年份分类更新 if (yrDocs.length > 0) { const uniqueDocs = Array.from(new Set(yrDocs)); uniqueDocs.forEach(docID => { const docRef = doc(firestore, "multichoice", docID); batch.update(docRef, { ["Year"]: arrayUnion(YRValue), ["Updated"]: timestamp }); }); } try { await batch.commit(); } catch (error) { console.error("批量更新失败:", error); } };
2. 调整validateData函数,直接传递临时数组
const validateData = async () => { setSearching(true); const ei = selectedFields.examInstitute; const yr = selectedFields.year; const EITemp = []; const YRTemp = []; // 遍历选中的文档ID,筛选需要更新的项 for (const docID of selectedDocsID) { const response = await fetchDoc("multichoice", docID, false); if (!response) continue; // 跳过不存在的文档 const EIField = response["ExamInstitute"]; const YRField = response["Year"]; // 判断是否需要添加到考试机构待更新列表 if (!EIField || !EIField.includes(ei)) { EITemp.push(docID); } // 判断是否需要添加到年份待更新列表 if (!YRField || !YRField.includes(yr)) { YRTemp.push(docID); } } // 直接传递临时数组执行更新,无需依赖状态 await saveData(EITemp, YRTemp); setSearching(false); // 结束后恢复按钮状态 };
优化点说明
- 移除了不必要的状态更新(
setEI、setYR),减少组件无意义重渲染 - 合并
batch.update的多次调用,降低Firestore批量操作的任务数量 - 增加文档不存在的容错处理,避免后续逻辑报错
内容的提问来源于stack exchange,提问作者Aly
相关产品推荐
相关产品推荐

