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.