Reputation: 13
Someone please help. I have combed all of the doc's, examined all similar questions and really cannot see what I am missing.
I am new to react and trying to map over documents returned from an asynchronous call from a firebase db.
Here is the code:
class Posts extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
let posts = [];
db.collection("Posts").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
posts.push({
data: doc.data(),
id: doc.id
});
});
});
this.setState({
data: posts
});
}
renderPosts() {
console.log(this.state.data);
return this.state.data.map((post, index) => {
console.log(post);
console.log(index);
return (
<div>
{index}
</div>
)
})
}
render() {
return(
<div>
{this.renderPosts()}
</div>
);
}
}
I am sure it is something super simple but I am pulling my hair out. If I examine my state I can see the data. console.log(this.state.data); inside renderPosts even displays exactly what I need to map over, but everything inside the map callback doesn't return and I end up with a single empty Any help would be greatly appreciated.
Upvotes: 0
Views: 3030
Reputation: 598765
As Li357 commented, the setState
call needs to happen inside the get()
callback:
db.collection("Posts").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
posts.push({
data: doc.data(),
id: doc.id
});
});
this.setState({
data: posts
});
});
The reason for this is that data is loaded from Firestore asynchronously, and by the time you were calling setState
the posts
variable was still empty.
The easiest way to understand this type of asynchronous loading is with a few log lines:
console.log("Before starting to get documents");
db.collection("Posts").get().then(function(querySnapshot) {
console.log("Got documents");
});
console.log("After starting to get documents");
When you run this, the output is:
Before starting to get documents
After starting to get documents
Got documents
That is probably not the order you expected the output in. But it is the expected behavior: instead of blocking the code while the data is loaded (which would freeze the browser), the code after the get().then()
block immediately executes. And then when the data is loaded, the code in the then
callback is executed. That's why all code that needs the documents from the database needs to be inside the then
callback.
Upvotes: 2