React项目中Firebase Firestore读取数据重复两次的问题求助
解决Firestore数据读取重复的问题
嘿,我帮你找到了数据重复的原因和解决办法:
问题根源
- React 18 Strict Mode的影响:在开发环境下,React 18的Strict Mode会自动让
useEffect执行两次,目的是帮你检测潜在的副作用问题。 - State更新方式不对:你现在的代码是在
forEach循环里逐个调用setPosts((posts) => [...posts, payload]),每次都往现有数组里追加数据。第一次执行fetchData时把所有文档都加到数组里,第二次执行时又重新遍历所有文档再追加一遍,结果就导致数据重复了。
修复方案
最直接的办法是先把所有Firestore文档数据收集到一个完整的数组里,再一次性更新state,这样即使useEffect执行两次,每次都是用新的完整数组替换旧数组,不会出现累加重复的情况。
修改后的useEffect代码如下(两种写法任选其一):
写法1:用forEach收集数据
useEffect(() => { const fetchData = async () => { const postRef = collection(db, 'posts'); const postSnap = await getDocs(postRef); // 先创建一个空数组,收集所有文档数据 const fetchedPosts = []; postSnap.forEach(doc => { const payload = { id: doc.id, ...doc.data() }; fetchedPosts.push(payload); }); // 一次性设置整个数组 setPosts(fetchedPosts); } fetchData() .catch(console.error); }, [])
写法2:用map更简洁
useEffect(() => { const fetchData = async () => { const postRef = collection(db, 'posts'); const postSnap = await getDocs(postRef); // 直接用map把docs转换成我们需要的数组格式 const fetchedPosts = postSnap.docs.map(doc => ({ id: doc.id, ...doc.data() })); setPosts(fetchedPosts); } fetchData() .catch(console.error); }, [])
额外优化建议
你现在在渲染PostSnippet时用了idx作为key,这其实不太推荐——如果数组顺序变化或者内容更新,React可能会出现渲染异常。建议换成每个文档唯一的article.id作为key:
{ _.map(posts, (article) => { return ( <PostSnippet key={article.id} id={article.id} title={article.title} content={article.content.substring(0, 300)} /> ) }) }
这样修改后,不管是开发环境还是生产环境,数据都不会再重复啦~
内容的提问来源于stack exchange,提问作者Udayendu
相关产品推荐
相关产品推荐

