Reputation: 880
The following function extracts images stored on a firebase storage and logs their URL to the console. I have tried multiple ways to pass the URL extracted to the Image for display on the screen. All images URL is successfully logged but won't display.
EDITED: Added the full code
The listFilesAndDirectories function was placed outside the const Gallery
declaration, putting function inside Gallery
still doesn't change anything.
I also tried passing the state to a variable and passing as the uri to no avail
import React, {setState} from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
TouchableOpacity,
Image,
} from 'react-native';
import Header from '../shared/header';
import firebase from '@react-native-firebase/app';
import storage from '@react-native-firebase/storage';
import Hamburg from '../shared/hamburg';
import SharedStyles from '../shared/sharedStyle';
import {DrawerActions, useNavigation} from '@react-navigation/native';
const Gallery: () => React$Node = () => {
const navigation = useNavigation();
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
// call getDownloadURL on every object reference
ref.getDownloadURL().then(url => {
setState({url: url});
console.log(
`File is referenced from :\n ${storageReference}:\n\n Image URL is:\n ${url}`,
);
});
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}
const storageReference = firebase
.storage()
.refFromURL('gs://app404.com/images');
listFilesAndDirectories(storageReference).then(() => {
// storageReference.getDownloadURL();
console.log('Started listing image download urls');
});
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<View style={SharedStyles.header}>
<TouchableOpacity
onPress={() => {
navigation.dispatch(DrawerActions.openDrawer());
}}>
<Hamburg />
</TouchableOpacity>
<Header title="Gallery" />
</View>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={styles.container}>
<View style={styles.sectionContainer}>
<View>
<Text>
Welcome to my Gallery!
</Text>
<Image
source={{
uri: {url} //url is not defined
}}
style={styles.fetchedImage}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
);
};
const Gallery: () => React$Node = () => {
const navigation = useNavigation();
const [downloadUrl, setDownloadUrl] = useState({url: undefined});
console.log(`URL should be undefined at this point ${downloadUrl}`);
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
// call getDownloadURL on every object reference
ref.getDownloadURL().then(url => {
setDownloadUrl({url});
console.log(`Image URL is:\n ${url}`);
});
});
and inside the image component:
<Image
source={{
uri: {...downloadUrl.url},
}}
style={styles.fetchedImage}
/>
Upvotes: 0
Views: 991
Reputation: 599816
Since the URLs are being determined through asynchronous operations, you can't return them to the render method. Instead you'll need to store them in the state, and render them from there:
function listFilesAndDirectories(reference, pageToken) {
reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
ref.getDownloadURL().then(url => {
setState({ url: url });
});
});
if (result.nextPageToken) {
listFilesAndDirectories(reference, result.nextPageToken);
}
});
}
const storageReference = firebase
.storage()
.refFromURL('gs://app404.appspot.com/images');
listFilesAndDirectories(storageReference);
And then:
<View>
<Text>
Welcome to my Gallery! Come back for more content.
</Text>
<Image
source={{
uri: {url}
}}
style={styles.fetchedImage}
/>
</View>
If you want to wait for the multiple images, have a look here: How to list all the names and download Urls from Firebase using React JS? or Firebase storage: download images to and put to img src in React map
Upvotes: 1