------------------------- | Cloud Storage Upload | |-----------------------| | [Select Image Button] | | | | [Upload Button] | | | | Progress: 0% | | | | [Uploaded Image Here] | -------------------------
Cloud Storage in React Native - Mini App: Build & Ship
import React, { useState } from 'react'; import { View, Button, Image, Text, StyleSheet } from 'react-native'; export default function CloudStorageUpload() { const [imageUri, setImageUri] = useState(null); const [uploadProgress, setUploadProgress] = useState(0); const [uploadedImageUrl, setUploadedImageUrl] = useState(null); // TODO: Add function to select image from gallery // TODO: Add function to upload image to cloud storage return ( <View style={styles.container}> <Button title="Select Image" onPress={() => { /* TODO */ }} /> <View style={{ height: 20 }} /> <Button title="Upload Image" onPress={() => { /* TODO */ }} disabled={!imageUri} /> <View style={{ height: 20 }} /> <Text>Progress: {uploadProgress}%</Text> {uploadedImageUrl && <Image source={{ uri: uploadedImageUrl }} style={styles.image} />} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', alignItems: 'center' }, image: { width: 200, height: 200, marginTop: 20 } });
import React, { useState } from 'react'; import { View, Button, Image, Text, StyleSheet, Alert } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import { getStorage, ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'; import { initializeApp } from 'firebase/app'; const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_MESSAGING_SENDER_ID", appId: "YOUR_APP_ID" }; const app = initializeApp(firebaseConfig); const storage = getStorage(app); export default function CloudStorageUpload() { const [imageUri, setImageUri] = useState(null); const [uploadProgress, setUploadProgress] = useState(0); const [uploadedImageUrl, setUploadedImageUrl] = useState(null); async function pickImage() { const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (permissionResult.granted === false) { Alert.alert('Permission required', 'Permission to access gallery is required!'); return; } const pickerResult = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, quality: 1 }); if (!pickerResult.cancelled) { setImageUri(pickerResult.uri); setUploadedImageUrl(null); setUploadProgress(0); } } async function uploadImage() { if (!imageUri) return; const response = await fetch(imageUri); const blob = await response.blob(); const storageRef = ref(storage, `images/${Date.now()}.jpg`); const uploadTask = uploadBytesResumable(storageRef, blob); uploadTask.on('state_changed', (snapshot) => { const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); setUploadProgress(progress); }, (error) => { Alert.alert('Upload failed', error.message); }, () => { getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { setUploadedImageUrl(downloadURL); }); }); } return ( <View style={styles.container}> <Button title="Select Image" onPress={pickImage} /> <View style={{ height: 20 }} /> <Button title="Upload Image" onPress={uploadImage} disabled={!imageUri} /> <View style={{ height: 20 }} /> <Text>Progress: {uploadProgress}%</Text> {uploadedImageUrl && <Image source={{ uri: uploadedImageUrl }} style={styles.image} accessibilityLabel="Uploaded image" />} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', alignItems: 'center' }, image: { width: 200, height: 200, marginTop: 20 } });
This solution uses the expo-image-picker library to let the user select an image from their device gallery. It first asks for permission to access the gallery and shows an alert if permission is denied.
Once an image is selected, its URI is saved in state. The upload button becomes enabled.
When the user taps upload, the image file is fetched as a blob and uploaded to Firebase Storage using uploadBytesResumable. This method provides progress updates, which we use to update the progress percentage shown on screen.
After the upload completes, the download URL is retrieved and saved in state. The uploaded image is then displayed using an Image component.
This approach keeps the UI responsive and informs the user about the upload progress. Accessibility is considered by adding an accessibility label to the uploaded image.
------------------------- | Cloud Storage Upload | |-----------------------| | [Select Image Button] | | | | [Upload Button] | | | | Progress: 75% | | | | [Uploaded Image Here] | -------------------------