Home > Software design >  useEffect does not store state for Firebase data on initial load and only shows up after fast refres
useEffect does not store state for Firebase data on initial load and only shows up after fast refres

Time:11-09

UPDATE

@Chris's answer below helped me with my issue. Installed the React Firebase Hooks package and set up my code as seen below. Everything is working flawlessly now! :)

const [value] = useCollection(collection(db, `${sessionUserId}`), {
    snapshotListenOptions: { includeMetadataChanges: true },
  })
  useEffect(() => {
    if (value) {
      const allData = JSON.parse(
        JSON.stringify(
          value?.docs.map((doc) => ({
            id: doc.id as string,
            resultData: doc.data() as DocumentData,
          }))
        )
      )
      setAllLogs(allData)
    }
  }, [value])

What am I using in my project? NextAuthjs, Firebase, Recoiljs


I have a useRecoilState hook to save logs that users have created.

const [allLogs, setAllLogs] = useRecoilState(modalAllLogs)

The modalAllLogs looks like this:

export const modalAllLogs = atom<Array<DocumentData>>({
  key: 'allLogs',
  default: [],
})

Here is the issue. I have a useEffect hook that grabs the data the user has from the database and assigns setAllLogs to that data. Note: I * do not * have the state updating anywhere else.

useEffect(() => {
    const docQuery = query(
      collection(db, `${sessionUserId}`),
      orderBy('timestamp', 'desc')
    )
    const unsubscribe = onSnapshot(
      docQuery,
      (snapshot: QuerySnapshot<DocumentData>) => {
        const data = JSON.parse(
          JSON.stringify(
            snapshot.docs.map((doc: QueryDocumentSnapshot<DocumentData>) => ({
              id: doc.id as string,
              resultData: doc.data() as DocumentData,
            }))
          )
        )
        setAllLogs(data)
      }
    )
    return unsubscribe
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [db])

What happens is, on initial render, allLogs returns an empty array, which makes sense, but stays empty until I make any edit within the same file the useEffect hook is in, save it, and NextJS triggers it's fast render, only then does allLogs suddenly display the data properly. I did a console.log(snapshot) and it is empty on every initial render as well.

Whenever I add data using the inputs I have created, Firebase stores all the data properly and correctly. The only issue is when the data is not loaded in on initial render. Other than that, I have no other issues.

I am not sure what I am doing wrong here. Maybe it is the RecoilState that I am utilizing wrong?

I have tried many things from other forums - changing the dependency to allLogs (which gave me an infinite loop), tried using getDocs() instead of onSnapshot(), and etc.

CodePudding user response:

The problem here is, that the useEffect isn't triggered because the "db" constant doesn't change.

Have a look at these custom hooks for Firebase/firestore https://github.com/CSFrequency/react-firebase-hooks/tree/master/firestore or lift the onSnapshot up to get real-time results. But in the last case the renders won't be triggered so I think it's the best to make use of custom hooks.

  • Related