------------------------- | 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] | -------------------------
Practice
What is the main purpose of Cloud Storage in a React Native app?
Solution
Step 1: Understand Cloud Storage role
Cloud Storage is used to save and get files online, not for UI or navigation.Step 2: Match purpose with options
Only To save and retrieve files online easily describes saving and retrieving files online.Final Answer:
To save and retrieve files online easily -> Option AQuick Check:
Cloud Storage = Save/Get files online [OK]
- Confusing Cloud Storage with UI components
- Thinking Cloud Storage manages app navigation
- Assuming Cloud Storage handles local state
Which of the following is the correct way to create a reference to a file named image.jpg in Cloud Storage?
const storage = getStorage();
const ref = ?Solution
Step 1: Recall correct syntax for reference
In React Native Firebase, use ref(storage, 'filename') to create a reference.Step 2: Check options for correct function
Only ref(storage, 'image.jpg') uses ref(storage, 'image.jpg') correctly.Final Answer:
ref(storage, 'image.jpg') -> Option CQuick Check:
Reference creation = ref(storage, 'filename') [OK]
- Using storage.ref() which is not valid in React Native
- Calling getRef() which does not exist
- Using storage.getReference() which is incorrect
What will the following code do?
const storage = getStorage();
const fileRef = ref(storage, 'docs/report.pdf');
await uploadBytes(fileRef, fileData);
const url = await getDownloadURL(fileRef);
console.log(url);Solution
Step 1: Analyze uploadBytes usage
The code uploads fileData to 'docs/report.pdf' using uploadBytes with await.Step 2: Analyze getDownloadURL usage
After upload, it gets the file's URL and prints it with console.log.Final Answer:
Upload the file and print its download URL -> Option AQuick Check:
Upload + get URL = print URL [OK]
- Thinking getDownloadURL works before upload
- Missing await causing runtime errors
- Assuming uploadBytes does not upload file
Identify the error in this code snippet for uploading a file:
const storage = getStorage();
const fileRef = ref(storage, 'photos/pic.png');
uploadFile(fileRef, fileData);
const url = await getDownloadURL(fileRef);
console.log(url);Solution
Step 1: Check function names for uploading
The correct function to upload is uploadBytes, not uploadFile.Step 2: Verify other code parts
getDownloadURL can be awaited and ref usage is correct.Final Answer:
uploadFile is not a valid function -> Option DQuick Check:
uploadBytes is correct upload function [OK]
- Using uploadFile instead of uploadBytes
- Forgetting to await uploadBytes
- Misusing getDownloadURL without await
You want to upload a profile picture and then immediately show it in your app. Which sequence of steps is correct?
- Get a reference to the file location
- Upload the file using
uploadBytes - Get the download URL using
getDownloadURL - Display the image using the URL
Solution
Step 1: Create file reference first
You must first get a reference to where the file will be stored.Step 2: Upload file using uploadBytes
Upload the file to that reference location.Step 3: Get download URL after upload
Only after upload can you get the file's URL.Step 4: Display image using URL
Use the URL to show the image in your app.Final Answer:
1 -> 2 -> 3 -> 4 -> Option BQuick Check:
Reference -> Upload -> URL -> Display [OK]
- Trying to get URL before uploading
- Uploading before creating reference
- Displaying image without URL
Ready to prove it?
Pass the test and this pattern moves unknown
