Skip to content
Advertisement

Firestore Pagination, how to?

I can’t really seem to wrap my head around how this is done. Don’t think the documentation is explaining it very well, or maybe I’m just not getting it 🙂

What I’m trying to do is have a list that start out by showing X items. Then with a click of a button load the next X items in the collection…

I’ve created this generic function which I can call:

let latestDoc = null;

export const getDocumentsPaginated = async <T extends { id?: string }>(collectionPath: string, numberOfDocs: number) => {
  const items: T[] = [];
  const q = query(collection(db, collectionPath), orderBy('createdAt', 'desc'), startAfter(latestDoc || 0), limit(numberOfDocs));
  const querySnapshot = await getDocs(q);
  console.log('querySnapshot', querySnapshot)
  latestDoc = querySnapshot.docs[querySnapshot.docs.length - 1];
  querySnapshot.forEach((doc) => {
    const data = doc.data();
    items.push({
      ...data,
      id: doc.id
    } as T);
  });

  return items;
};

Then trying to call it from a Vue component:

const fetchExercises = async () => {
      isLoading.value = true;
      try {
        const result = await getDocumentsPaginated<ExerciseDocument>(`exercises/${companyId}/exercises`, 5);
        console.log('internal', result);
        exercises.value = result;
        isLoading.value = false;
      } catch (e) {
        throw new Error('cant load exercises ' + e);
      }
    };

This does not seem to work. I just get an empty array back even though I know the collection has a lot of documents?

What am I doing wrong? Just really use a helping hand

Advertisement

Answer

Firestore pagination does not work based on offsets, so you’re adding 20 to a counter will not work (as you’ve found).


Firestore pagination works based on cursors object. This means that to query for the documents on the second page, you must know the data of the last item on the first page.

Since you orderBy('createdAt', 'desc'), you will need to know the createdAt value (and the document ID) of the last document on the first page, and pass those to startAfter to get the documents for the second page.


The easiest way to make pagination work in Firestore is to keep the DocumentSnapshot of the last item of the current page around in a variable with something like:

const querySnapshot = await getDocs(q);
lastDocumentOnCurrentPage = querySnapshot.docs[querySnapshot.docs.length-1];

Then when you need to load the next page of data, you pass this variable to the startAfter condition of the query.

Advertisement