react firestore snapshot not a function - javascript

Hi so I followed firebase docs to get data from my collection. But I get error that snapshot is undefined.
This is what I tried:
const [data, setData] = useState([]);
useEffect(() => {
const db = Firestore.firestore();
// let tempData = Controller.getData();
const projects = db.collection('projects');
const snapshot = projects.get();
let fireData = [];
snapshot.forEach((doc) => {
console.log('data:', doc.data());
fireData.push(doc.data());
});
setData(fireData);
});
I tried TypeError: snapshot.forEach is not a function
But then I het data() is undefined plz help

projects.get() returns a promise that resolves with a QuerySnapshot object. It doesn't directly return the snapshot. You have to wait for the promise to resolve in order to get the data, as illustrated in the documentation:
projects.get().then(snapshot => {
let fireData = [];
snapshot.forEach((doc) => {
console.log('data:', doc.data());
fireData.push(doc.data());
});
setData(fireData);
});

Related

Get firestore data as array

Im tryng to display firestore data but I just get one value. I have try forEach and map. Nothing is working. Heres my code:
React.useEffect(() => {
retrieveNetwork();
}, []);
const retrieveNetwork = async () => {
try {
const q = query(collection(db, "cities", uidx, "adress"));
const querySnapshot = await getDocs(q);
let result = [];
//querySnapshot.docs.map((doc) => setGas(doc.data().home));
querySnapshot.docs.map((doc) => {
result.push(doc.data().home);
setGas(result);
});
} catch (e) {
alert(e);
}
};```
The .map method returns an array (official docs here), so you could do something like this:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
React.useEffect(() => {
retrieveNetwork();
}, []);
const retrieveNetwork = async () => {
try {
const q = query(collection(db, "cities", uidx, "adress"));
const querySnapshot = await getDocs(q);
// an array from the docs filled only with "home" data
const results = querySnapshot.docs.map((doc) => {
return doc.data().home;
});
// only update the state once per invokation
setGas(results)
} catch (e) {
alert(e);
}
};

My async await method for fetching docs in Firestore using getDocs() returns an empty array

My async await method for fetching docs in Firestore using getDocs() returns an empty array.
I'm using React.js.
Thing is, this fetching-data-function is placed within a useEffect() hook with an empty array [] as a dependency (so that it runs, and hence fetches data from the Firestore database only once), and right after, the data is console logged. Output is an empty array.
allData: []
But if I just somehow get the useEffect() hook to run once more (like making a tiny change in the code and saving it - essentially just refreshing it on the local host), the array is populated with the desired data from the database.
This is the code:
import db from "./firebase";
useEffect(() => {
console.log("use effect ran");
const temp = async () => {
const q = query(collection(db, "blogs"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
const newblog = {
id: doc.id,
title: doc.data().title,
content: doc.data().content,
};
setAllData((prev) => [...prev, newblog]);
});
};
temp();
console.log("allData: ", allData);
}, []);
I can't quite figure out what the issue is. I'd be grateful for some help.
You are seeing a empty array in allData because the console.log("allData: ", allData) is running before than setAllData((prev) => [...prev, newblog]) because the async function temp doesn't run in the same thread so the interpreter continues reading the code that follows. To fix it add await to temp() like this: await temp() and wrap it like I do in the following code.
import db from "./firebase";
useEffect(() => {
console.log("use effect ran");
(async () => {
const temp = async () => {
const q = query(collection(db, "blogs"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
const newblog = {
id: doc.id,
title: doc.data().title,
content: doc.data().content
};
setAllData((prev) => [...prev, newblog]);
});
};
await temp();
console.log("allData: ", allData);
})();
}, []);

How to get specific data from all documents from a collection in firebase?

Platform: React Native (Expo)
So I'm trying to get two values (dotCoins and name) from my firebase db and I can't figure out how to go about it. Here's my firebase structure:
This is what I currently have in place:
// Calling function when screen loads
componentDidMount() {
this.getDotCoins();
this.getUserData();
}
// Calling function when it updates
componentDidUpdate() {
this.getDotCoins();
this.getUserData();
}
// The function
getUserData = async () => {
const querySnapshot = await getDocs(collection(db, "users"));
const tempDoc = [];
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
});
console.log(tempDoc);
};
Both the console.log() prints nothing, and my console remains absolutely empty. I can't find where I'm going wrong since I don't receive any errors too. (I have all packages installed correctly and all functions imported too)
You are not pushing any document data to tempDoc so it'll always be empty. Try refactoring the code as shown below:
getUserData = async () => {
const querySnapshot = await getDocs(collection(db, "users"));
const tempDoc = querySnapshot.docs.map((d) => ({
id: d.id,
...d.data()
}));
console.log(tempDoc);
};
const q = query(collection(db, "users"));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(doc.data())
})
});
});
return unsubscribe;

Uncaught FirebaseError: Expected type 'mc', but it was: a custom ln object

useEffect(() => {
const q = query(collection(db, "posts"));
const querySnapshot = getDocs(q);
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
});
}, []);
I'm trying to access all documents from my firestore collection.
but it throws an error FirebaseError: Expected type 'mc', but it was: a custom ln object
I think you need to put await in getDocs (or then). Then you should use an async function that is called inside useEffect and not directly call it inside useEffect.
Something like this should work:
const myFunction = async () => {
const q = query(collection(db, "posts"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
});
}
useEffect(() => {
myFunction();
}, []);

Why i can't access list of array in react

I fetch some date and get array and i can console.log and see all staff but when i try map or access of some elements from array i got error undefined...
and get this
Unhandled Rejection (TypeError): Cannot read property 'map' of undefined
const [key, setKey] = useState(false);
const [country, setCountry] = useState([]);
const [nextFive, setFive] = useState([]);
useEffect(() => {
getWeather();
}, [key]);
const getCity = async (e) => {
e.preventDefault();
const cityName = e.target.elements.cityName.value;
const api_call = await fetch(`http://dataservice.accuweather.com/locations/v1/cities/search?apikey=${process.env.REACT_APP_WEATHER_API_KEY}&q=${cityName}&details=true`);
const data = await api_call.json();
setKey(data[0].Key);
setCountry(data[0]);
return data[0].Key;
}
const getWeather = async (cityKey = key) => {
const proxy = `https://cors-anywhere.herokuapp.com/`;
const link = `${proxy}http://dataservice.accuweather.com/forecasts/v1/daily/5day/${cityKey}?apikey=${process.env.REACT_APP_WEATHER_API_KEY}&details=true&metric=true`;
const api_call = await fetch(link);
const data = await api_call.json();
setFive(data.DailyForecasts);
};
console.log(nextFive); if i tray console.log(nextFive[0].something) i will get error :)
console.log(country);
{
nextFive.map((item) => {
return <p>{item.Date}</p>
})
}
and get this Unhandled Rejection (TypeError): Cannot read property 'map' of undefined
This happends because you try to show first element of item in array that is not yet populated.
You could have extra hook called as example weatherLoading, once api call is succesfuly you would set status of weatherLoading to true and then simply do this:
weatherLoading && console.log(nextFive[0].something)

Categories