Home > front end >  how do i display data from firebase firstore getDocs function?
how do i display data from firebase firstore getDocs function?

Time:10-30

I'm a little new to firestore ,I'm trying to take a data object from firestore set it as state, and then display it:

these are my imports ignore the chakra imports they are for easy styling.

import { useContext, useEffect, useState } from "react";
import { useRouter } from "next/router";
import { collection, doc, getDoc, getDocs, query } from "firebase/firestore";
import { auth, db } from "../../lib/firebase";
import { useAuthState } from "react-firebase-hooks/auth";
import { onAuthStateChanged } from "firebase/auth";
import HotTakes from "../../comps/HotTakes";
import {
  Heading,
  Image,
  Skeleton,
  Stack,
  Text,
  VStack,
} from "@chakra-ui/react";
import { UserContext } from "../../lib/context";



 const { username } = useContext(UserContext);
      const [user] = useAuthState(auth);

  const [takes, settakes] = useState(null);

this is my get data function.

const getData = async () => {

// if user is present run function 

if (user) {

  const docRef = doc(db, "users", user.uid);
  const collectionRef = collection(docRef, "takes");
  const querySnapshot = await getDocs(collectionRef);

  // from firebase docs

  querySnapshot.forEach((doc) => {
    // doc.data() is never undefined for query doc snapshots
    console.log("getData()", doc.id, " => ", doc.data());

    settakes(querySnapshot);
  });
} else {
  console.log("user Not avaible rn");
}
console.log("takes object:", takes);
  };

as you can see I'm setting the data that I get into a "takes" state variable and with all the console logs it always returns null even after the data is recieved:enter image description here

here is the useEffect:

useEffect(() => {
    getData();
  }, [user]);

this is how I'm trying to render my data:

<div>

    <Image borderRadius={"50%"} src={user?.photoURL} alt="photo" />
    <Text>
      <i>{user?.displayName}</i>
    </Text>
    {/* if ! takes then we render this message */}
    {takes?.length == 0 ? (
      <>
        {takes?.length}
        <Heading>{`${username} does not have any takes`}</Heading>
      </>
    ) : (
      <>
      {/* if we do have takes then we grab the takes property in our  object and pass it down to this component to render */}
        {takes?.forEach((doc) => {
          <HotTakes take={doc.data().take} />;
        })}
      </>
    )}
  </div>

the main problem im having is im not able to set my setstate for some reason once that issue is solved then my component will render out all of the takes.

CodePudding user response:

You are using the settakes() within the forEach() so the state is being update multiple times. Also, try settings an array of objects in state instead of the QuerySnapshot as shown below:

// set default state to empty array []
const [takes, settakes] = useState([]);
const querySnapshot = await getDocs(collectionRef);

const data = querySnapshot.docs.map((d) => ({
  id: d.id,
  ...d.data()
}))

settakes(data);
{
  takes.map((take) => {
    <p>{take.take}</p>
  })
}
  • Related