简体   繁体   中英

How do I get all documents in a Cloud Firestore collection using Version 9 of the Modular Web SDK?

I am trying to get all documents in a collection using version 9 of the Web SDK. But I am getting this error:

"TypeError: querySnapshot.map is not a function"

This is the component where I get the error:

import { useEffect, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../../firebase";
function CurrentUser() {
  const [names, setNames] = useState([]);
  async function getMakers() {
    const querySnapshot = await getDocs(collection(db, "users"));
    querySnapshot.map((doc) => {
      setNames((doc.id = doc.data()));
    });
  }
  getMakers();
  return <div>{names.map((doc) => doc.firstName)}</div>;
}
export default CurrentUser;

querySnapshot is an instance of a QuerySnapshot object, not a JavaScript Array. This means it doesn't have the normal Array methods like map() , some() and includes() . However, it does have its own version of a forEach() method that can be used to iterate over the entries in the snapshot. If you need to access methods of a normal array, you can use the snapshot's docs property instead (which internally calls forEach() to assemble an array).

To correctly fetch the documents in the array, optionally plucking the first names of each returned document, you can use any of the following strategies:

  • Option 1: useState and useEffect for each user's complete data
import { useEffect, useState } from "react";

// ...

const [userDataArray, setUserDataArray] = useState([]);

useEffect(() => {
  let unsubscribed = false;

  getDocs(collection(db, "users"))
    .then((querySnapshot) => {
      if (unsubscribed) return; // unsubscribed? do nothing.
      
      const newUserDataArray = querySnapshot.docs
        .map((doc) => ({ ...doc.data(), id: doc.id }));

      setUserDataArray(newUserDataArray);
    })
    .catch((err) => {
      if (unsubscribed) return; // unsubscribed? do nothing.

      // TODO: Handle errors
      console.error("Failed to retrieve data", err);
    });

  return () => unsubscribed  = true;
}, []);

return (
  <div>
    { userDataArray.map((userData) => userData.firstName) }
  </div>
);
  • Option 2: useState and useEffect for just each user's firstName
import { useEffect, useState } from "react";

// ...

const [firstNamesArray, setFirstNamesArray] = useState([]);

useEffect(() => {
  let unsubscribed = false;

  getDocs(collection(db, "users"))
    .then((querySnapshot) => {
      if (unsubscribed) return; // unsubscribed? do nothing.
      
      const newFirstNamesArray = querySnapshot.docs
        .map((doc) => doc.get("firstName"));

      setFirstNamesArray(newFirstNamesArray);

      // need to remove duplicates? use this instead:
      // const firstNamesSet = new Set();
      // querySnapshot
      //   .forEach((doc) => firstNamesSet.add(doc.get("firstName")));
      // 
      // setFirstNamesArray([...firstNamesSet]);
    })
    .catch((err) => {
      if (unsubscribed) return; // unsubscribed? do nothing.

      // TODO: Handle errors
      console.error("Failed to retrieve data", err);
    });

  return () => unsubscribed  = true;
}, []);

return (
  <div>
    { firstNamesArray }
  </div>
);
  • Option 3: Make use of a tree-shakeable utility library like react-use to handle intermediate states.
import { useAsync } from 'react-use';

// ...

const remoteUserData = useAsync(
  () => getDocs(collection(db, "users"))
);

if (remoteUserData.loading)
  return (<div>Loading...</div>);

if (remoteUserData.error) {
  console.error("Failed to load data! ", remoteUserData.error);
  return (<div class="error">Failed to load data!</div>);
}

const userDataArray = remoteUserData.value;

return (
  <div>
    { userDataArray.map((userData) => userData.firstName) }
  </div>
);

 useEffect(() => onSnapshot(collection(db, 'posts'), snapshot => { setPosts( snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })) ) }), [])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM