Infinite loop inserting docs in firebase after query in react

I am trying to get how many documents there are in the firestore to get a correlative document of the day and then save a new document with React. For some reason when I execute the function to save the new document that causes that firestore to add the new record on an infinite loop. Probably I am doing something wrong. Can someone point me out with the error?

this is my function that saves the new document.

import { db } from '../utils/init-firebase'
import { collection, query, onSnapshot, Timestamp, addDoc, where } from "firebase/firestore"


export interface ProjectState {
    projectId: string,
    name: string;
}

const saveProject = async (project: ProjectState) => {
    try {
        const today = Timestamp.fromDate(new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()));
        const q = query(collection(db, 'projects'), where('created', '>=', today));
        let count = 0

        const unsubscribe = onSnapshot(q, (querySnapshot) => {
            count = querySnapshot.docs.length + 1;
            
            const date = new Date();
            const month = twoDigitDate(date.getMonth() + 1);
            const day = twoDigitDate(date.getDate());
            const year = date.getFullYear().toString().slice(-2)

            const projectId = `${month}${day}${year}${count > 0 ? '-' + count : ''}`;

            const projectDoc = collection(db, 'projects');
            return addDoc(projectDoc, {
                projectId,
                name: project.name
                created: Timestamp.now(),
            });
        })

    } catch (err) {
        console.log('Error creating project:', err)
    }
}

const twoDigitDate = (date: number) => {
    return date < 10 ? `0${date}` : date;
}


export default saveProject;

Solution 1:

You have infinite loop because of onSnapshot() is a listener listen all time collection and when new document appear triggers again with all documents in snapshoot + one extra you added. Insted of onSnapshot() use getDocs() function.

import { collection, query, where, getDocs } from "firebase/firestore";

const q = query(collection(db, "cities"), where("capital", "==", true));

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

Your function should lool like this ?

const saveProject = async (project: ProjectState) => {
    try {
        const today = Timestamp.fromDate(new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()));
        const q = query(collection(db, 'projects'), where('created', '>=', today));
        let count = 0

        const querySnapshot = await getDocs(q)

        querySnapshot.forEach(doc => {
            // your code what ever you want to do.
        })

    } catch (err) {
        console.log('Error creating project:', err)
    }
}

I don't have any clue why you wanna make new docs in same collection according to old documents in this collection. You need to remember using only query you using now you will get max 100 documents.