React中使用Firebase getDocs与useEffect出现两次请求的问题
React中useEffect执行两次导致重复获取Firebase数据的解决方案
问题原因
- React 18的开发模式下,StrictMode会自动执行两次挂载相关的生命周期(包括useEffect),这是官方刻意设计的机制,用来帮开发者检测组件中可能存在的副作用问题,生产环境下不会触发该行为。
- 你的代码中,
setMusicList采用循环追加旧数组的方式更新状态,两次执行getData会直接导致数据重复叠加。
修复步骤
1. 先解决数据重复问题
修改getData函数,一次性整理所有Firebase返回的数据后再更新状态,避免多次调用setState,同时从根源上杜绝重复数据:
const getData = async () => { try { const querySnapshot = await getDocs(collection(db, "music")); // 一次性转换所有文档数据为数组,再更新状态 const newMusicList = querySnapshot.docs.map(doc => doc.data()); setMusicList(newMusicList); console.log("Did request!"); } catch (error) { console.log(error); } };
2. 处理StrictMode导致的两次请求(可选)
如果想在开发模式下彻底避免两次请求,可通过添加标志位控制:
useEffect(() => { let isMounted = true; const fetchData = async () => { // 组件卸载或重复执行时直接终止逻辑 if (!isMounted) return; try { const querySnapshot = await getDocs(collection(db, "music")); const newMusicList = querySnapshot.docs.map(doc => doc.data()); setMusicList(newMusicList); console.log("Did request!"); } catch (error) { console.log(error); } }; fetchData(); // 组件卸载时重置标志位 return () => { isMounted = false; }; }, []);
这种方式既能保留StrictMode的检测能力,又能避免无效的重复请求。
额外说明
生产环境打包后,StrictMode会自动失效,不会出现两次执行的情况。开发模式下的两次执行是React用来提前暴露潜在问题(比如内存泄漏、重复订阅)的机制,建议不要长期移除StrictMode。
内容的提问来源于stack exchange,提问作者Codesk
相关产品推荐
相关产品推荐

