应用重载后useEffect无法打印数据到控制台,仅保存应用时生效
问题:Firestore查询数据后,应用重载时控制台无法打印数据,仅保存代码后才显示
问题详情
我尝试查询云Firestore数据库并打印选中项,数据结构如下:
{ "name": "projects/myapp/databases/(default)/documents/place/wr8MvJQsmGI8QTbGJ3po", "fields": { "title": { "stringValue": "Hotel" } }, "createTime": "2022-10-14T08:32:16.920093Z", "updateTime": "2022-10-14T08:32:16.920093Z" }
导入语句:
import { collection, query, where, getDocs } from 'firebase/firestore'; import { db } from '../../../config';
当前使用的函数:
const AutoSearch = () => { const [returnedData, setReturnedData] = useState(''); let singleItems = []; useEffect(() => { const loadData = async () => { const q = query(collection(db, 'place'), where('title', '!=', null)); const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { singleItems.push(doc.data().title); setReturnedData(singleItems); }); }; loadData(); console.log(returnedData); }, []); // other code follows.......
遇到的问题:应用重载后,数据数组无法打印到控制台,只有保存代码(触发热更新)后才会打印数据。
问题原因及修复方案
1. 异步操作导致打印时机错误
loadData是异步函数,console.log(returnedData)会在Firestore请求完成前执行,此时returnedData还是初始的空字符串。同时setReturnedData是异步更新状态的,无法立刻同步获取更新后的值。
2. 状态更新方式不合理
- 循环中多次调用
setReturnedData会触发多次组件重渲染,效率低下 - 外部声明的
singleItems数组在组件每次渲染时都会重新初始化,状态更新逻辑存在隐患 returnedData初始值设为空字符串,但实际要存储数组,类型不匹配
修复后的代码
const AutoSearch = () => { // 初始值改为空数组,匹配数据类型 const [returnedData, setReturnedData] = useState([]); useEffect(() => { const loadData = async () => { const q = query(collection(db, 'place'), where('title', '!=', null)); const querySnapshot = await getDocs(q); // 一次性收集所有数据,避免循环更新状态 const items = querySnapshot.docs.map(doc => doc.data().title); setReturnedData(items); // 数据获取完成后直接打印 console.log('查询到的数据:', items); }; loadData(); }, []); // 监听状态变化,在状态更新后打印 useEffect(() => { console.log('状态更新后的returnedData:', returnedData); }, [returnedData]); // other code follows.......
关键说明
- 用
map一次性提取所有title,收集完成后再调用一次setReturnedData,减少不必要的重渲染 - 在异步函数内部、数据获取完成后直接打印,确保拿到最新数据
- 添加监听
returnedData的useEffect,可以在状态更新后触发打印,便于调试
内容的提问来源于stack exchange,提问作者Oao
相关产品推荐
相关产品推荐

