문제의 코드
const getList = async (pageParam: number) => {
const querySnapshot = await getDocs(
query(
collection(dbService, "recipe"),
orderBy(
isBest === "viewCount" ? "viewCount" : "createdAt",
"desc"
),
startAfter(pageParam),
limit(6)
)
);
const newData = querySnapshot.docs.map((doc: any) => ({
...doc.data(),
id: doc.id,
}));
setTotalItems((prev) => [...prev, ...newData]);
return totalItems;
};
const { fetchNextPage, hasNextPage } = useInfiniteQuery(
["infiniteRecipe"],
({ pageParam = 0 }) => getList(pageParam),
{
getNextPageParam: (querySnapshot) => {
const lastPageParam =
querySnapshot.docs[querySnapshot.docs.length - 1];
if (querySnapshot.size < 6) {
return undefined;
}
return lastPageParam;
},
}
);
startAfter(undefined)가 되어 유효하지 않은 조건이 되어 firebase 에러가 발생했다.
그래서 getList()를 first()와 next() 두 개의 함수로 분리해 보았다.
first는 초기 data 6개를 불러 오는 로직이고
next는 startAfter(firebase조건문)을 추가하여 기존data 바로 다음의 data 6개를 불러 오는 로직이다.
const first = async () => {
const querySnapshot = await getDocs(
query(
collection(dbService, "recipe"),
orderBy(
isBest === "viewCount" ? "viewCount" : "createdAt",
"desc"
),
limit(6)
)
);
const newData = querySnapshot.docs.map((doc: any) => ({
...doc.data(),
id: doc.id,
}));
setTotalItems(newData);
};
const next = async (pageParam: number) => {
const querySnapshot = await getDocs(
query(
collection(dbService, "recipe"),
orderBy(
isBest === "viewCount" ? "viewCount" : "createdAt",
"desc"
),
startAfter(pageParam),
limit(6)
)
);
const newData = querySnapshot.docs.map((doc: any) => ({
...doc.data(),
id: doc.id,
}));
setTotalItems((prev) => [...prev, ...newData]);
};
const { fetchNextPage, hasNextPage } = useInfiniteQuery(
["infiniteRecipe"],
async ({ pageParam }) => await (pageParam ? next(pageParam) : first()),
{
getNextPageParam: (querySnapshot) => {
const lastPageParam =
querySnapshot?.docs[querySnapshot.docs.length - 1];
if (querySnapshot?.size < 6) {
return undefined;
}
return lastPageParam;
},
}
);
getNextPageParam에서 first()와 next()의 querySnapshot을 받아오지 못했다.
최종 코드
// 전체목록(6개씩)
const first = async () => {
const querySnapshot = await getDocs(
query(
collection(dbService, "recipe"),
orderBy(
isBest === "viewCount" ? "viewCount" : "createdAt",
"desc"
),
limit(6)
)
);
const newData = querySnapshot.docs.map((doc: any) => ({
...doc.data(),
id: doc.id,
}));
setTotalItems(newData);
return querySnapshot;
};
// 더보기event
const next = async (pageParam: number) => {
const querySnapshot = await getDocs(
query(
collection(dbService, "recipe"),
orderBy(
isBest === "viewCount" ? "viewCount" : "createdAt",
"desc"
),
startAfter(pageParam),
limit(6)
)
);
const newData = querySnapshot.docs.map((doc: any) => ({
...doc.data(),
id: doc.id,
}));
setTotalItems((prev) => [...prev, ...newData]);
return querySnapshot;
};
//쿼리문
const { fetchNextPage, hasNextPage } = useInfiniteQuery(
["infiniteRecipe"],
async ({ pageParam }) => await (pageParam ? next(pageParam) : first()),
{
getNextPageParam: (querySnapshot) => {
const lastPageParam =
querySnapshot.docs[querySnapshot.docs.length - 1];
if (querySnapshot.size < 6) {
return undefined;
}
return lastPageParam;
},
}
);
return (
<InfiniteScroll
loadMore={() => fetchNextPage()}
hasMore={hasNextPage}
loader={<div>불러오는 중...</div>}
>
{totalItems?.map((item) => {
return (
<div key={item.id} className="aspect-[1/0.7]">
...
</InfiniteScroll>
first()와 next()에 각각
return querySnapshot;
으로 return문으로 처리하여 getNextPageParam이 querySnapshot을 인자로 넘겨 받을 수 있도록 고쳐주었다.
6개씩 불러오도록 설정하였는데 querySnapshot.size < 6 (불러와야 할 data의 개수가 6개이하)일 때는 undefined를 반환하여 더 이상 스크롤이 작동하지 않고 그 외에는 (불러와야 할 data의 개수가 6개이상) 스크롤이 작동하여 data를 불러 온다.