Firestore数据在useEffect加载异常:刷新后session ID数组为空致查询失败
问题分析与修复方案
核心问题
- 异步函数未正确返回Promise:
getSessionIDs用了.then()但没返回Promise,导致await getSessionIDs()根本没等数据请求完成就继续执行,此时sessionIDs还是初始空数组,sessionIDArray自然也为空,刷新页面时就触发了Firestore的空数组查询错误。 - React State更新的异步性:即使
getSessionIDs正确返回Promise,setSessionIDs是异步操作,await getSessionIDs()之后立刻访问sessionIDs,拿到的还是更新前的旧值,还是会导致sessionIDArray为空。 - 组件内普通变量的重置问题:
sessionIDArray是组件内的普通数组,每次组件渲染都会被重置为空,不能用来存储持久化的临时数据。 - useEffect依赖缺失:原useEffect依赖数组为空,但实际依赖
currentUser,如果currentUser是异步加载的,初始渲染时currentUser可能为null,会导致后续查询出错。
修复后的代码
export default function Sessions() { const { currentUser } = useAuth(); const [sessions, setSessions] = useState([]); // 封装获取用户关联session ID的函数,直接返回ID数组 const getUserSessionIDs = async () => { if (!currentUser) return []; const query = collection(users, currentUser.uid, "sessions"); const response = await getDocs(query); return response.docs.map(doc => doc.id); }; // 封装根据ID获取session详情的函数 const fetchSessionsByIDs = async (ids) => { if (ids.length === 0) { setSessions([]); return; } const q = query(allSessions, where('__name__', "in", ids)); const response = await getDocs(q); const sessionList = response.docs.map(doc => ({ data: doc.data(), id: doc.id })); setSessions(sessionList); }; useEffect(() => { // 组合异步逻辑 const loadData = async () => { const sessionIDs = await getUserSessionIDs(); await fetchSessionsByIDs(sessionIDs); }; loadData(); }, [currentUser]); // 依赖currentUser,确保用户状态变化时重新加载 if (!currentUser) { return <div>请先登录</div>; } return ( <div> <h2>Awe {currentUser.uid}</h2> <ul> {sessions.map((session) => ( <li key={session.id}> {session.data.location} </li> ))} </ul> </div> ); }
关键修复点
- 让异步函数返回Promise:
getUserSessionIDs用async/await改写,直接返回session ID数组,避免依赖State中转,绕开State异步更新的问题。 - 合并异步逻辑:在useEffect里封装
loadData函数,按顺序先获取ID,再查详情,逻辑更清晰。 - 添加正确的依赖:useEffect依赖
currentUser,确保用户登录状态变化时重新执行数据加载,同时处理currentUser为null的情况,避免报错。 - 去掉冗余变量:删掉
sessionIDs状态和sessionIDArray普通变量,直接在异步流程中传递ID数组,减少不必要的State操作。
内容的提问来源于stack exchange,提问作者notGoodAtThis
相关产品推荐
相关产品推荐

