【发布时间】:2020-11-28 03:25:23
【问题描述】:
我正在实现一个分页,用户单击一个按钮来加载更多项目。 我正在关注https://firebase.google.com/docs/firestore/query-data/query-cursors 的文档(对查询进行分页)
我将最后一个项目 id 传递给 startAfter() 函数。这应该使下一个查询返回传入项 id 之后的项。
实际发生的是,之前的项目再次加载。 因此,如果初始提取看起来像:
[
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
2: {id: "3", stuff: ...}
]
id 3 将被传递给 startAfter(),并且应该加载
[
0: {id: "4", stuff: ...}
1: {id: "5", stuff: ...}
]
相反,它会加载初始项目
[
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
]
所以当我按下“加载更多”按钮时,我最终会显示重复的项目。
初始获取函数:
const [recipes, setRecipes] = useState([]);
useEffect(() => {
const fetchData = async () => {
const obj = [];
const firstFetch = await db
.collection('recipes')
.orderBy('createdAt', 'desc')
.limit(3)
.get();
const snapshot = await firstFetch;
snapshot.forEach((doc) => {
obj.push({ id: doc.id, ...doc.data() });
});
const allRecipes = {
userRecipes: obj,
};
setRecipes(allRecipes.userRecipes);
};
fetchData();
}, []);
配方变量日志:
[
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
2: {id: "3", stuff: ...}
]
加载更多项目的按钮:
<button
type="button"
onClick={() => showMore({ recipe: recipes[recipes.length - 1] })}
>
Show More
</button>
调用showMore函数:
const showMore = async ({ recipe }) => {
const data = await db
.collection('recipes')
.orderBy('createdAt', 'desc')
.startAfter(recipe)
.limit(2)
.get();
const moreData = data.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
setRecipes([...recipes, ...moreData]);
};
如果我记录 'moreData' 变量:
[
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
]
如果我记录更新后的“配方”变量:
[
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
2: {id: "3", stuff: ...}
0: {id: "1", stuff: ...}
1: {id: "2", stuff: ...}
]
所以对我来说,它似乎忽略了 startAfter() 函数,而是从头开始加载所有内容。
任何关于我做错了什么的指针?
编辑: db 中的实际数据如下所示:
{
about: "Non magnam quasi tempore."
createdAt: t {seconds: 1596741068, nanoseconds: 531000000}
description: "Ea quibusdam odit quasi corporis et nostrum."
imageUrl: "http://lorempixel.com/640/480/food"
ingredients: [{…}]
likes: []
title: "Ella"
userId: "U8n09jb0ZENwrZhDeYrJUSikcM12"
userSaves: ["uM7A4r5O6ENiX3qTL4tGhDXYA3Z2"]
username: "foobar"
}
ID 是文档的名称。 ID 会在初始提取函数中附加到文档中。
解决方案:
查看 Frank van Puffelen 的回答,我必须提供完整的快照(其中包括有关项目的所有信息),而不仅仅是包含项目的数组。
通过使用 useState 创建一个新的钩子,我可以在其中存储最后一个快照的状态:
const last = snapshot.docs[snapshot.docs.length - 1]
setLastDocSnap(last)
在我的 fetchMore() 函数中,我能够在 startAfter() 函数中设置状态:
const data = await db
.collection('recipes')
.orderBy('createdAt')
.limit(limit)
.startAfter(lastDocSnap)
.get();
【问题讨论】:
标签: javascript reactjs firebase google-cloud-firestore pagination