1

I am building an app in NextJS which uses Firebase authentication. After successful authentication, I then wish to fetch additional details about the customer stored within a MongoDB instance (or create a new document for the customer on first login). Because I cannot access the firebase auth object inside getServerSideProps, I have redirected after firebase.auth() to /dashboard/${user.uid} which then getsServerSideProps using the uid passed to fetch customized/dynamic content.

dashboard.js

export default function DashboardAuth(props) {
  
  const [user, loading, error] = useAuthState(firebase.auth())
     if (user){
         return window.location.href = `/dashboard/${user.uid}`
     } else {
         return <SignIn/>
     }
}

/dashboard/[id].js


export async function getServerSideProps({ params }) {

    let userData 
    console.log("Logging in ")
    const { db } = await connectToDatabase();
    console.log("connected to database, awaiting query response with uid")
    const findUserResp = await db
      .collection("users")
      .findOne({'uid': params.id})
    
    if(findUserResp ){
      console.log("user data exists")
      userData = {
        uid: findUserResp.uid,
        email: findUserResp.email,
        displayName: findUserResp.displayName,
        photoURL: findUserResp.photoURL,
        storageQuoteRemaining: findUserResp.storageQuoteRemaining,
        emailVerified: findUserResp.emailVerified,
        currentPage: '/dashboard'
      }
    }else{
        console.log("user data does not exist") 
        userData = {
            uid:params.id,
            email: '',
            displayName: '',
            photoURL: '',
            storageQuoteRemaining: 0,
            emailVerified: false,
            currentPage: '/dashboard'
        }
        const addUserResp = await db
            .collection("users")
            .insertOne(userData)

    }
    console.log("returning userdata below")
    console.log(userData)
    return {
      props: {
        userData
      }
    }
}


export default function Dashboard(props) {
  
  const [user, loading, error] = useAuthState(firebase.auth())
  const userContext = getUserContext()
  useEffect(() => {
    userContext.handleCurrentUser(props.userData)
    }, []);
  if (user && props.userData.uid === user.uid){
    return  <Layout  children={<CreateItem/>}/>
  }else{
    return <SignIn/>
  }
    
  }

My main issue is that after the user is initially added to mongodb on first login, immediatley after redirect to [id].js, I am presented with an error

Error: Error serializing `.userData._id` returned from `getServerSideProps` in "/dashboard/[id]".
Reason: `object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.

but on refresh this disappears.

Also I don't like how I have written my redirect but useRouter does not work. Any advice on how to better do this would be appreciated.

raiyan22
  • 1,043
  • 10
  • 20
HubertBlu
  • 747
  • 1
  • 7
  • 20
  • Where does the `userData._id` come from? You don't seem to have an `_id` property in the `userData` object you return from `/dashboard/[id].js`'s `getServerSideProps`. – juliomalves Jan 10 '22 at 23:46
  • Also: _"useRouter does not work"_ - the ``router.push(`/dashboard/${user.uid}`)`` call needs to run inside a `useEffect` with `user` in its dependencies array. – juliomalves Jan 10 '22 at 23:48

1 Answers1

0
  1. Looks like your first issue is related to what is being said here - https://github.com/vercel/next.js/issues/11993#issuecomment-617375501. The solve being to:

JSON.parse(JSON.stringify(findUserResp)) which is the data returned.

  1. You should do a middleware solve (NextJS 12) as explained here or a redirect key inside your getServerSeideProps if using older than NextJS 12
 if (user) {
    return {
      redirect: {
        destination: '/dashboard/${user.uid}',
        permanent: false,
      },
    }
Guillem Puche
  • 1,199
  • 13
  • 16
Ramakay
  • 2,919
  • 1
  • 5
  • 21
  • thanks for that, the first part doesnt work, - and when a user logs in for the first time, the userdata is constructed and then passed to the component, as opposed to being retrieved from mongo. and its only this time when i receive the error. it actually performs the post twice for some reason which might have something to do with it. another issue I am unable to resolve! Middelware seems like a good idea, but I'm just gonna use plain react as i also cannot access the global context from getserversideprops which is causing me even more headaches! I love NextJS why does it hate me! – HubertBlu Jan 10 '22 at 17:49
  • If possible, put up a minimal code example of your code on stack blitz or code sandbox to reproduce – Ramakay Jan 10 '22 at 17:51