SvelteKit无Vite热更新时部分页面数据无法加载问题
问题解决:SvelteKit + Firebase 刷新页面数据不渲染问题
问题根源
核心问题出在/[username]/requests/+layout.ts的异步遍历逻辑里:使用forEach执行异步getDoc请求时,forEach不会等待异步操作完成。当load函数返回incomingMail数组时,内部的Firebase文档查询还没结束,所以数组是空的。热更新时客户端可能复用了缓存或已有连接,后续异步请求完成后数据被填充,页面能正常显示;但刷新页面时,初始渲染依赖的是load返回的空数组,hydration完成后也不会自动触发更新。
修复代码
将forEach替换为Promise.all,确保所有异步查询完成后再返回数据:
// /[username]/requests/+layout.ts export const load = (async ({ parent }) => { const data = await parent() const collectionRef = collection(db, "requests"); const toQ = query( // incoming requests to this user's characters collectionRef, where("to", "in", data.characterList), ); interface Mail { to: DocumentData | undefined, from: DocumentData | undefined, type: string, } // 改用map生成Promise数组,再用Promise.all等待所有异步操作完成 const snapshot = await getDocs(toQ); const incomingMailPromises = snapshot.docs.map(async (mail) => { if (!mail.exists()) return null; const mailContent = mail.data(); const toDoc = await getDoc(doc(db, "characters", mailContent.to)); const fromDoc = await getDoc(doc(db, "characters", mailContent.from)); return { to: toDoc.data(), from: fromDoc.data(), type: mailContent.type }; }); // 过滤掉null值(对应不存在的mail文档) const incomingMail = (await Promise.all(incomingMailPromises)).filter(Boolean) as Mail[]; return { username : data.username, incomingMail : incomingMail, }; }) satisfies LayoutLoad;
额外建议
- 把Firebase的查询逻辑封装成独立工具函数,避免在load函数里写过多业务代码,提升可维护性
- 在
+page.svelte中添加加载状态,比如在数据未加载时显示加载提示:{#if !data.incomingMail.length} <div>加载中...</div> {:else} {#each data.incomingMail as mail} <div>TO: {mail.to?.name.first}</div> <div>FROM: {mail.from?.name.first}</div> {/each} {/if} - 检查Firebase安全规则,确保当前用户有权限读取
requests和characters集合的文档,避免因权限问题导致数据为空
内容的提问来源于stack exchange,提问作者goathead
相关产品推荐
相关产品推荐

