I am making a list of posts in a .map fetching from my Firebase Cloud Firestore. I also have photos connecting to each post, and I fetch them by using the post.title +
The download URL is loaded asynchronously. To see what this means, place a few log statements:
console.log("Before calling getDownloadURL")
firebase
.storage()
.ref(post.title + '.jpg')
.getDownloadURL()
.then((url) => {
console.log("Got URL")
});
console.log("After calling getDownloadURL")
When you run this code you get:
Before calling getDownloadURL
After calling getDownloadURL
Got URL
This is probably not the order you expected the output in. But it completely explains why your return
does not return the download URL: it hasn't been loaded yet.
The then()
callback from your call to getDownloadURL
runs after you return
the component that uses uri: fetchImage
. And you can't return a value that hasn't loaded yet.
The common solution in React is to store any data that is asynchronously loaded into the component's state.
this.state.posts.map((post, i) => {
let fetchImage
firebase
.storage()
.ref(post.title + '.jpg')
.getDownloadURL()
.then((url) => {
let state = {};
state[post.title+"_url"] = url
this.setState(state)
});
})
Since any call to setState()
forces the component to rerender itself, the new render will then pick up the updated download URL from the state.
return (
{post.title}