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:
useState
and useEffect
for each user's complete dataimport { 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>
);
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>
);
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.