React项目中Firestore食谱数据上传重复问题排查求助
问题原因分析与解决建议
核心原因
- React Strict Mode 双重执行:Vite默认启用React Strict Mode,开发环境下会触发
useEffect钩子两次。第一次执行上传时,setIsUploaded(true)是异步操作,第二次触发useEffect时isUploaded仍为false,导致上传逻辑重复执行。 - 状态未持久化:
isUploaded是组件内部状态,页面刷新后会重置为false,每次刷新都会重新执行上传流程,造成数据重复。 - 无重复数据校验:当前上传逻辑直接批量新增文档,未检查Firestore中是否已存在相同食谱,即使重复触发上传也会不断添加重复数据。
解决方案
方案1:添加重复数据校验(推荐)
修改uploadRecipesToFirestore函数,上传前先检查食谱是否已存在(通过唯一标识如食谱名称),仅新增不存在的数据:
export const uploadRecipesToFirestore = async (recipes) => { try { const recipesCollection = firebase.firestore().collection('recipes'); const batch = firebase.firestore().batch(); for (const recipe of recipes) { // 假设食谱的name字段唯一,以此查询是否已存在 const querySnapshot = await recipesCollection.where('name', '==', recipe.name).get(); if (querySnapshot.empty) { const newDocRef = recipesCollection.doc(); batch.set(newDocRef, recipe); } } await batch.commit(); console.log('Recipes uploaded to Firestore successfully!'); } catch (error) { console.error('Error uploading recipes to Firestore:', error); } };
方案2:持久化上传状态
将isUploaded状态存入localStorage,避免页面刷新后重复触发上传:
export const RecipesProvider = ({ children }) => { // 从localStorage初始化状态 const [isUploaded, setIsUploaded] = useState(() => { return localStorage.getItem('recipesUploaded') === 'true'; }); const [fetchedRecipes, setFetchedRecipes] = useState([]); useEffect(() => { if (!isUploaded) { uploadRecipesToFirestore(recipes) .then(() => { console.log('Recipes uploaded to Firestore successfully!'); setIsUploaded(true); localStorage.setItem('recipesUploaded', 'true'); }) .catch((error) => { console.error('Error uploading recipes to Firestore:', error); }); } }, [isUploaded]); // 其余原有代码保持不变 };
方案3:临时关闭Strict Mode(仅开发环境)
如果只是开发环境的临时问题,可在Vite配置中关闭React Strict Mode:
修改vite.config.js:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react({ strictMode: false })], });
额外说明
protobufjs原型污染漏洞与当前数据重复问题无关,无需为此修改Firebase版本,该漏洞不影响Firestore数据上传逻辑。
内容的提问来源于stack exchange,提问作者rubenaguirre
相关产品推荐
相关产品推荐

