Skip to content

Instantly share code, notes, and snippets.

@Yiork
Last active September 21, 2023 13:08
Show Gist options
  • Save Yiork/d5079241a756a06f1af50a2cbb935f26 to your computer and use it in GitHub Desktop.
Save Yiork/d5079241a756a06f1af50a2cbb935f26 to your computer and use it in GitHub Desktop.
firebase pagination hook typescript
import { useCallback, useMemo, useState } from "react";
import {
CollectionReference,
getDocs,
limit,
orderBy,
OrderByDirection,
query as q,
startAfter,
} from "@firebase/firestore";
type UsePagination<T> = {
collectionRef: CollectionReference;
initialData: T[];
paginationLimit: number;
paginationOrder: OrderByDirection;
};
export function useFirestorePagination<T>({
collectionRef,
initialData,
paginationLimit,
paginationOrder,
}: UsePagination<T>) {
const [genericList, setGenericList] = useState(initialData);
const [loading, setLoading] = useState(false);
const [genericListEnd, setGenericListEnd] = useState(false);
const getMore = useCallback(async () => {
setLoading(true);
const cursor = genericList[genericList.length - 1].createdAt;
const query = q(
collectionRef,
orderBy("createdAt", paginationOrder),
startAfter(cursor),
limit(paginationLimit),
);
const newGenericsSnapshot = await getDocs(query);
const newGenerics = newGenericsSnapshot.docs.map((doc) => ({
...doc.data(),
id: doc.id,
})) as T[];
setGenericList((prevState) => [...prevState, ...newGenerics]);
setLoading(false);
if (newGenerics.length < paginationLimit) {
setGenericListEnd(true);
}
}, [setLoading, setGenericList, setGenericListEnd, genericList]);
return useMemo(
() => ({ list: genericList, loading, listEnd: genericListEnd, getMore }),
[genericList, loading, genericListEnd, getMore],
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment