Svelte结合Firebase实现无限滚动加载时Firestore报data.hits未定义错误求助
报错根因
你代码里触发的访问undefined属性length报错,核心是混淆了示例接口和Firestore接口的返回数据结构,没有复杂的底层逻辑问题。
为什么data.hits是undefined
- 你参考的svelte无限加载示例,对接的是模拟搜索接口,本身返回结构就把列表数据存在
hits字段下,这个字段和Firestore的返回逻辑完全无关 - Firestore调用
get()拿到的结果是QuerySnapshot快照对象,压根没有hits这个字段,它存储查询结果的属性是docs——数组里的每一项都是单个匹配到的文档对象,需要你手动调用doc.data()才能取出实际存储的字段值 - 你现在写的
startAfter(page*5)分页逻辑本身在Firestore里是不生效的:Firestore不支持按页码偏移量分页,必须传入上一页最后一条文档的位置作为游标,才能正确实现翻页拉取,否则会出现重复拉取、漏数据的问题
可直接用的修正代码
<script> import InfiniteLoading from "svelte-infinite-loading"; // 替换成你项目里实际初始化的Firestore db实例导入路径 import { db } from "$lib/firebase"; let list = []; // 提前定义存储内容的响应式数组 let lastDoc = null; // 记录上一页最后一条文档,作为分页游标 let hasNoMoreData = false; async function fetchData({ detail: { loaded, complete } }) { // 已经拉完全部数据就直接触发完成状态 if (hasNoMoreData) { complete(); return; } // 初始化基础查询规则 let query = db .collection("todos") .orderBy("created", "desc") .limit(5); // 不是第一页的话,从上次记录的最后一条文档之后开始拉 if (lastDoc) { query = query.startAfter(lastDoc); } const snapshot = await query.get(); // 拉到空快照说明已经到列表末尾 if (snapshot.empty) { hasNoMoreData = true; complete(); loaded(); return; } // 从Firestore快照中解析出实际业务数据,字段结构可以根据自己的集合定义调整 const newContent = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // 更新游标为当前页的最后一条文档 lastDoc = snapshot.docs.at(-1); // 拼接新数据到现有列表 list = [...list, ...newContent]; loaded(); } </script> <Box> <!-- 渲染实际列表内容的逻辑 --> {#each list as block (block.id)} <!-- 对应ContentBlocks的渲染逻辑 --> {/each} <InfiniteLoading on:infinite={fetchData} /> </Box>
容易踩的小坑
- 不要漏了定义
list变量,否则首次执行数组拼接时会触发未定义变量报错 - 不要试图用页码偏移的方式写Firestore分页,哪怕简单计算页码值,也会因为数据新增/删除导致分页错位
- 如果需要实时同步数据,可以把一次性的
get()查询替换为onSnapshot()监听,注意做数据去重避免重复渲染
内容的提问来源于stack exchange,提问作者Gnai Hari
相关产品推荐
相关产品推荐

