I’m trying to adapt a React Native project to the new Firebase
methods. In it I upload images to Storage and they are added to the App interface. I can also remove these images from the interface as shown in the following code:
const removeImage = (img) => { // delete an image selected by the user Alert.alert( "Eliminar imagen", "¿Estás seguro de eliminar esta imagen?", [ { text: "Cancelar", style: "cancel", }, { text: "Eliminar", onPress: () => { const result = filter( formik.values.images, (image) => image !== img ) formik.setFieldValue("images", result) }, }, ], { cancelable: false } ) }
The problem is that in this way, they are only removed from my App, while the images are still stored in Firebase
. My idea is that when I remove the images from the frontend, they will also be removed from the Firebase Storage
.
I have read Firebase documentation, and this would be possible with the deleteObject function
const storage = getStorage(); // Create a reference to the file to delete const desertRef = ref(storage, 'images/desert.jpg'); // Delete the file deleteObject(desertRef).then(() => { // File deleted successfully }).catch((error) => { // Uh-oh, an error occurred! })
I did some test, and I can’t get it to work. I don’t know exactly how I should add the Firebase instructions shown here.
How should I implement this function in my code to remove images from Storage?
Thank you
import { getStorage, ref, deleteObject, uploadBytes, getDownloadURL } from "firebase/storage" export function UploadImagesForm(props) { const { formik } = props const [isLoading, setIsLoading] = useState(false) // status for loading // Function in charge of opening the image gallery const openGallery = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.All, allowsEditing: true, aspect: [4, 3], quality: 1, }) if (!result.cancelled) { // console.log('buscando imagenes') setIsLoading(true) // uploading the image uploadImage(result.uri) } } // function to upload the images to Firebase const uploadImage = async (uri) => { const response = await fetch(uri) const blob = await response.blob() const storage = getStorage() const storageRef = ref(storage, `restaurants/${uuid()}`) // we go to storage where we want to save the images uploadBytes(storageRef, blob).then((snapshot) => { // console.log(snapshot) updatePhotosRestaurant(snapshot.metadata.fullPath) }) } // we take the URL in the previous function and set it in the state of the form const updatePhotosRestaurant = async (imagePath) => { const storage = getStorage() const imageRef = ref(storage, imagePath) const imageUrl = await getDownloadURL(imageRef) // get the url // code to upload all images without replacing them // get the current images and add the new ones with the array formik.setFieldValue("images", [...formik.values.images, imageUrl]) setIsLoading(false) } const removeImage = (img) => { // delete an image selected by the user Alert.alert( "Eliminar imagen", "¿Estás seguro de eliminar esta imagen?", [ { text: "Cancelar", style: "cancel", }, { text: "Eliminar", onPress: () => { const result = filter( formik.values.images, (image) => image !== img ) formik.setFieldValue("images", result) }, }, ], { cancelable: false } ) } return ( <> <ScrollView style={Styles.viewImage} horizontal showsHorizontalScrollIndicator={false} > <Icon type="material-community" name="camera" color="#a7a7a7" containerStyle={Styles.containerIcon} onPress={openGallery} /> {map(formik.values.images, (image) => ( // display the images on the screen <Avatar key={image} source={{ uri: image }} containerStyle={Styles.imageStyle} onPress={() => removeImage(image)} /> ))} </ScrollView> <Text style={Styles.error}>{formik.errors.images}</Text> <LoadingModal show={isLoading} text="Subiendo la imagen" /> </> ) }
Advertisement
Answer
I finally figured out where to implement the deleteObject function in my file to make it all work. You can delete the images from the Application and Firebase Storage at the same time. I found a React expert who helped me with this.
As the Firebase documentation says:
To delete a file, first create a reference to that file.
( const imageRef = ref(storage, img ))
Firebase explains it like this:
import { getStorage, ref, deleteObject } from "firebase/storage"; const storage = getStorage(); // Create a reference to the file to delete const desertRef = ref(storage, 'images/desert.jpg');
Then call the delete() method, (in my case: deleteObject(imageRef) ), for that reference, which will return either a Promise that resolves, or an error if the Promise is rejected.
import { getStorage, ref, deleteObject } from "firebase/storage"; const storage = getStorage(); // Create a reference to the file to delete const desertRef = ref(storage, 'images/desert.jpg'); // Delete the file deleteObject(desertRef).then(() => { // File deleted successfully }).catch((error) => { // Uh-oh, an error occurred! });
I just hope this can help other users who are in my situation learning Firebase
I show. the complete file so that they do not have the doubts that I had, which was the correct place where I should place the Firebase methods
const storage = getStorage() const imageRef = ref(storage, img) deleteObject(imageRef).then(() => { // also remove the image from Firebase console.log("la imagen se elimino"); }).catch((error) => { console.log("ocurrio un error: ", error) })
Thanks to @FrankvanPuffelen and @BhavyaKoshiya who tried to help.
import { getStorage, ref, uploadBytes, getDownloadURL, deleteObject } from 'firebase/storage' import { v4 as uuid } from 'uuid' import { map, filter } from 'lodash' import { LoadingModal } from '../../Shared/LoadingModal/LoadingModal' import Styles from './Styles' export function UploadImagesForm(props) { const { formik } = props const [isLoading, setIsLoading] = useState(false) // status for loading // Function in charge of opening the image gallery const openGallery = async () => { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.All, allowsEditing: true, aspect: [4, 3], quality: 1, }) if (!result.cancelled) { // console.log('buscando imagenes') setIsLoading(true) // uploading the image uploadImage(result.uri) } } // function to upload the images to Firebase const uploadImage = async (uri) => { const response = await fetch(uri) const blob = await response.blob() const storage = getStorage() const storageRef = ref(storage, `restaurants/${uuid()}`) // we go to storage where we want to save the images uploadBytes(storageRef, blob).then((snapshot) => { // console.log(snapshot) updatePhotosRestaurant(snapshot.metadata.fullPath) }) } // we take the URL in the previous function and set it in the state of the form const updatePhotosRestaurant = async (imagePath) => { const storage = getStorage() const imageRef = ref(storage, imagePath) const imageUrl = await getDownloadURL(imageRef) // get the url // code to upload all images without replacing them // get the current images and add the new ones with the array formik.setFieldValue("images", [...formik.values.images, imageUrl]) setIsLoading(false) } const removeImage = (img) => { // delete an image selected by the user Alert.alert( "Eliminar imagen", "¿Estás seguro de eliminar esta imagen?", [ { text: "Cancelar", style: "cancel", }, { text: "Eliminar", onPress: async () => { const result = filter( formik.values.images, (image) => image !== img ) formik.setFieldValue("images", result) **// THIS IS THE CODE I ADDED FROM FIREBASE** const storage = getStorage() const imageRef = ref(storage, img) deleteObject(imageRef).then(() => { // also remove the image from Firebase console.log("la imagen se elimino"); }).catch((error) => { console.log("ocurrio un error: ", error) }) **// END OF THE CODE I ADDED FROM FIREBASE** }, }, ], { cancelable: false } ) }