skip to Main Content

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?

2

Answers


  1. 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])
    
    Login or Signup to reply.
  2. 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])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search