'Setting image source to Firebase Storage URL with React Native
So I am trying to set a image source to the download url that I get back from Firebase Storage...the issue is that it is not showing the image but the console and download url both show correct Storage urls to pictures... here is my code that I currently have:
this.state = {
itemDataSource: ds,
modalVisible: false,
user: undefined,
imgSource: undefined,
};
getTrucks(truckRef, storageRef) {
truckRef.once('value', (snap) => {
console.log(snap.val());
// console.log(snap.key);
let trucks = [];
snap.forEach((trucksSnap) => {
console.log(trucksSnap.key);
uid = trucksSnap.key;
this.setState({user: uid});
trucksSnap.forEach((truckSnap) => {
console.log(truckSnap.key);
console.log(truckSnap.val());
let truck = truckSnap.val();
trucks.push({
uid: uid,
name: truck.name,
food: truck.foodType,
desc: truck.description,
menu: truck.menu,
phone: truck.phone,
});
});
});
console.log(trucks);
this.setState({
itemDataSource: this.state.itemDataSource.cloneWithRows(trucks)
});
});
}
getPics(storageRef) {
setTimeout(() => {
storageRef.ref('trucks/' + this.state.user + '/pic-1').getDownloadURL()
.then((url) => {
console.log(url);
this.setState({imgSource: url});
});
}, 3000);
}
<Image
source={{uri: this.state.imgSource}}
style={styles.iosCardImage}/>
the Image is in the render function and there is no image that shows up on screen but the console shows it other wise as the actual url that I can click on and see the image
I did look at other example questions though there was not an actual working answer posted or checked as correct.
React-Native: Download Image from Firebase Storage
Load and return an image from Firebase database/storage in React Native
React Native is at version 0.45.1 & Firebase is at version 4.1.3
Can someone please help me to set the source tag correctly who has done it before? Thank you
Solution 1:[1]
For future reference for other people here is the way(s) to do this... you do however as @marcST mentioned you have to set height and width in your styles either with React Natives inline styling or with and external stylesheet. Here are the 2 methods you can accomplish this, I am posting this since there is not a valid answer here on StackOverflow of how to do this correctly in React Native
1st way: so there are a couple of things you will need to note about this way.
- This is when you use
.push()
to add data to your Firebase database/storage - you first need state to be set to
undefined || null || ''
- you should use
shouldComponentMount()
because some of the data will not come in before the component mounts to the screen - you will need to
JSON.stringify
the URL coming back from yourgetDownloadURL()
this.state = { itemDataSource: ds, modalVisible: false, user: undefined, imgSource: undefined, };
shouldComponentUpdate(nextState) {
return nextState.imgSource !== this.state.imgSource;
}
getTrucks(truckRef, storageRef) {
truckRef.once('value', (snap) => {
console.log(snap.val());
// console.log(snap.key);
let trucks = [];
snap.forEach((trucksSnap) => {
console.log(trucksSnap.key);
uid = trucksSnap.key;
this.setState({user: uid});
trucksSnap.forEach((truckSnap) => {
console.log(truckSnap.key);
console.log(truckSnap.val());
let truck = truckSnap.val();
trucks.push({
uid: uid,
name: truck.name,
food: truck.foodType,
desc: truck.description,
menu: truck.menu,
phone: truck.phone,
});
});
});
console.log(trucks);
this.setState({
itemDataSource: this.state.itemDataSource.cloneWithRows(trucks)
});
});
}
getPics(storageRef) {
setTimeout(() => {
storageRef.ref('trucks/' + this.state.user + '/pic-1').getDownloadURL()
.then((url) => {
console.log(url);
let imgURL = JSON.stringify(url)
this.setState({imgSource: imgURL});
});
}, 3000);
}
<Image
source={{uri: this.state.imgSource}}
style={styles.iosCardImage}/>
2nd way:
- use
.set()
to add data to your firebase database - I used
.set()
to add the URL coming back on load to save into my Firebase database under an 'image' folder... see picture below code - When you put download URL's into your database you do not need to run the
snapshot.forEach
multiple times just to access your data, because you bypass the unique ID set by pushing that Firebase sets every time you push. - When you pull data from the database with image URL's you do not need to
JSON.stringify
them to add as image URI. - You do not need to set state to add the URL as the URI source
- You can now use dot notation to access your data as you would a normal JSON object
this is my component code that solves this...
getTrucks(truckRef) {
truckRef.on('value', (snap) => {
console.log(snap.val());
let truck = snap.val();
let trucks = [];
snap.forEach((truck) => {
trucks.push({
uid: truck.key,
name: truck.val().data.name,
food: truck.val().data.foodType,
desc: truck.val().data.description,
menu: truck.val().data.menu,
phone: truck.val().data.phone,
pic1: truck.val().mainImage.pic1,
pic2: truck.val().image2.pic2,
pic3: truck.val().image3.pic3,
pic4: truck.val().image4.pic4,
pic5: truck.val().image5.pic5,
pic6: truck.val().image6.pic6
});
console.log(trucks);
});
this.setState({
itemDataSource: this.state.itemDataSource.cloneWithRows(trucks),
});
});
}
<Image
source={{uri: truck.pic1}}
style={styles.iosCardImage}/>
this is the database code with the set method I am talking about
let url = task.snapshot.downloadURL;
trucksRef.child(user).child('mainImage').set({pic1: url});
trucksRef.child(firebaseUser.uid).child('data').set({
name: $('#name').val(),
foodType: $('#food').val(),
description: $('#description').val(),
address: $('#address').val(),
city: $('#city').val(),
zip: $('#zip').val(),
phone: $('#phone').val(),
menu: $('#menu').val(),
});
the picture in reference to what happens in your database if you use .set()
instead of .push()
If you have other questions please let me know about this
Solution 2:[2]
I had a problem similar to this where I had the correct download URL but the Image wasn't showing. It's quite likely the Image isn't being displayed because of a styling issue. What's in iosCardImage? If you haven't already, try defining width and height. Try doing:
<Image
source={{uri: this.state.imgSource}}
style={{ height: 200 }}/>
and see if the Image shows.
Solution 3:[3]
I fixed the problem with this... path/android/app/src/main/AndroidManifest.xml
android:largeHeap="true
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:largeHeap="true"
android:theme="@style/AppTheme">
I see android:largeHeap="true" as an accepted solution very often but this is not the right solution. We just enlarge the heap (if the target device has an ability to do so) which means that your application might work longer but might fail eventually anyway.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | T. Evans |
Solution 2 | marcst |
Solution 3 | Kenap |