Home > front end >  useEffect with firebase and nextjs undefined when page first loads
useEffect with firebase and nextjs undefined when page first loads

Time:08-28

I have a component that pulls in a subcollection from firestore:

import { useEffect, useState } from "react";
import { db } from '../firebase/firebaseInit'
import {useAuth} from '../components/AuthContextProvider'
import { collection, getDocs, setDoc, doc, addDoc } from "firebase/firestore"; 

type Inputs = {
  name: string,
  gender: string,
  date: any,
}

function Subscriptions({ Component, pageProps }: any) {
  const { user  } = useAuth()
  const [kids, setKids] = useState<any>([])

  useEffect(() => {
    const getKids = async (user: any) => {
      if (user) {
        const KidsCollectionRef = collection(doc(collection(db, "users"), user.uid), "kids")
        const data = await getDocs(KidsCollectionRef)
        setKids(data.docs.map((doc) => ({
          ...doc.data(), id: doc.id
        })))
        console.log(kids)
      }
    }
    getKids(user)
  }, [])

  return (
    <>
      <h1>Welcome back</h1>
      {/* need to loop throug the different prices */}
      <div>
        {kids.map((kid, index) => (
          <span key={index} style={{display: 'block', width: '100%'}}>
            {kid.name}
          </span>
        ))}
      </div>
    </>
    )
}

export default Subscriptions

But it only console.logs the data from kids if I change useEffect to this:

  useEffect(() => {
    const getKids = async (user: any) => {
      if (user) {
        const KidsCollectionRef = collection(doc(collection(db, "users"), user.uid), "kids")
        const data = await getDocs(KidsCollectionRef)
        setKids(data.docs.map((doc) => ({
          ...doc.data(), id: doc.id
        })))
        console.log(kids)
      }
    }
    getKids(user)
  }, [kids])

Which isn't ideal as it causes an infinite loop.

Here's the console.logs:

enter image description here

How do I make useEffect update when it gets the data from firestore?

CodePudding user response:

Just add user.uid to useEffect dep, uid doesn't change, but it can be either undefined or a value, meaning it will trigger on value only

  useEffect(() => {
    const getKids = async () => {
      if (user) {
        const KidsCollectionRef = collection(doc(collection(db, "users"), user.uid), "kids")
        const data = await getDocs(KidsCollectionRef)
        setKids(data.docs.map((doc) => ({
          ...doc.data(), id: doc.id
        })))
        console.log(kids)
      }
    }
    getKids()
  }, [user?.uid])

CodePudding user response:

If you want to look at new kids, you can do so before the change state, in setKids.

useEffect(() => {
  //... 
  setKids(() => {
    const newState = data.docs.map((doc) => ({...doc.data(), id: doc.id}))
    console.log(newState);
    return newState;
  })
}, []) 

Or just add another useEffect

// useEffect with fetch
useEffect(() => { //... }, [])

// useEffect with log
useEffect(() => {
  console.log(kids)
}, [kids])
  • Related