Simplified code that I am using:
import { useState, useEffect, useContext } from 'react'
import { useRouter } from 'next/router'
import { firestore } from './firebase-config'
import { getDoc, doc } from 'firebase/firestore'
export default function HomePage() {
const router = useRouter()
const user = useContext(AuthContext) // contains user object -> user.user
const [loading, setLoading] = useState(true)
useEffect(() => {
const getData = async() => {
setLoading(true)
const uid = user.user.uid // uid of user in firebase auth
const id = router.query.id // id param of url
const docRef = doc(firestore, `...`)
// doc in a collection that references the above uid and id
const docSnap = await getDoc(docRef)
// get the document from firestore
if (docSnap.exists()) {
importData(docSnap.data()) // add data to store to re-render page
setLoading(false)
} else {
router.push('/main')
// if the user isn't logged in to return to '/'
// ^^ not sure how to do these separately
// if the user is logged in but the document does not exist to return to '/main'
}
}
getData()
}, [router.query, user.user])
return (
<>
{/* */}
</>
)
}
I need to load the document associated with the user’s uid
and the id
param of the currently loaded page, i.e. /main/[id]
.
These retrieve a Firestore document that is then inserted into the store which causes the HomePage function to re-render to show the data.
uid
is found in user.user.uid
which is set via onAuthStateChanged
in app.js
id
is found in router.query.id
which is set via useRouter()
at the top level
The useEffect()
above works, but only temporarily, soon after the data is loaded and the component re-renders, I am linked to '/main'
as initially uid
and id
start as undefined
meaning that on the first run of the useEffect
hook the else
condition is run, it then re-runs as the user
and router
object is retrieved to load the data, but by the time that has occurred the page is transitioned to './main'
.
Would greatly appreciate some help to make this function work.
Additionally, the user should go back to './main'
if the document doesn’t exist but they are logged in, and if they are not logged in to then be returned to the root ('./'
)
Thanks in advance!
2
Answers
So I have managed to fix the issue:
To be able to use
uid
in theuseEffect()
hook,onAuthStateChanged
is called again rather than using theAuthContext
that is created at the top level as this will wait until the user existsTo wait for
router.query
to be updated you can callrouter.isReady
which returns aBoolean
value on whether it has been updated.Using both of these in this way:
You can add a loading state for the document retrieval in addition to the loading state that you already have to make sure that the document retrieval is completed before navigating away from the page.