How to display all the images from firebase storage in React? - javascript

I am trying to display images from Firebase storage in my React app.
I could get all images from Firebase Storage using by listall.
but I don't know how to display these on ui.
I tried to use map method but didn't work.
Also, I want to keep these display even if page is reload.
should I use localstrage or useEffect?
plz help me.
here is my code.
const PhotoButton = () => {
var storageRef = firebase.storage().ref("images");
const [image, setImage] = useState("");
const [imageUrl, setImageUrl] = useState([]);
const handleImage = event => {
const image = event.target.files[0];
setImage(image);
};
const onSubmit = event => {
event.preventDefault();
if (image === "") {
console.log(“error);
return;
}
const uploadTask = storage.ref(`/images/${image.name}`).put(image);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
next,
error,
complete
);
};
const complete = () => {
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(fireBaseUrl => {
setImageUrl(fireBaseUrl);
});
};
// Now we get the references of these images
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
// And finally display them
console.log(result.items);
displayImage(imageRef);
});
}).catch(function(error) {
alert(“error!”)
});
function displayImage(imageRef) {
imageRef.getDownloadURL().then(function(url) {
setImageUrl.push(url);
// TODO: Display the image on the UI
}).catch(function(error) {
// Handle any errors
});
}
return(
<div>
<h3 className={classes.addPhotoText}>Photos</h3>
<div className="addphoto">
<form onSubmit={onSubmit}>
<input type="file" onChange={handleImage} />
<Button type="submit" className={classes.PhotoButton}>Submit</Button>
</form>
</div>
<img src={imageUrl} />
{imageUrl.map((url) => (
<img src={url}/>
))}
</div>
);
}
export default PhotoButton

It worked with this code.
useEffect(() => {
const fetchImages = async () => {
let result = await storageRef.child('images').listAll();
let urlPromises = result.items.map(imageRef => imageRef.getDownloadURL());
return Promise.all(urlPromises);
}
const loadImages = async () => {
const urls = await fetchImages();
setFiles(urls);
}
loadImages();
}, []);

For me i needed to add some things to #via answer to get it to work. I hoop it can help others
Firebase config
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/storage";
import "firebase/auth";
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: "",
};
if (firebase.apps.length === 0) {
firebase.initializeApp(firebaseConfig);
}
const auth = firebase.auth();
const db = firebase.firestore();
const storage = firebase.storage();
export { db, storage, auth };
code
import { storage } from "../components/config/config";
// Get all the images from Storage
const [files, setFiles] = useState();
useEffect(() => {
const fetchImages = async () => {
let result = await storage.ref().child("Name Of Your Files Map in storage").listAll();
let urlPromises = result.items.map((imageRef) =>
imageRef.getDownloadURL()
);
return Promise.all(urlPromises);
};
const loadImages = async () => {
const urls = await fetchImages();
setFiles(urls);
};
loadImages();
}, []);
console.log(files);

Related

Firestorage download urls not working as img sources

I'm using getDownloadURL from fire storage to get a url for any image that is uploaded on to the server. But when I try to display the images in my img element source, it returns a blank icon instead of the actual image. The image even on firestorage has trouble rendering and when its opened, its just a white square instead of the image. The function is the sendImage function in the code. Ive also added CORS configuration to my google cloud shell and changed the meta data multiple times, and yes the images do have tokens and the rules are fine. Any help .
import React, { useContext, useEffect, useRef, useState } from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faPaperclip, faImage, faPaperPlane } from '#fortawesome/free-solid-svg-icons'
import { doc, db } from '../firebase'
import { arrayUnion, onSnapshot, setDoc, updateDoc } from 'firebase/firestore'
import ChatContext from '../Context/ChatContext'
import { AuthContext } from '../Context/AuthContext'
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
const Chat = () => {
const {user} = useContext(AuthContext)
const [messages, setMessages] = useState([])
const {data} = useContext(ChatContext)
const [file, setFile] = useState()
const [msg, setMsg] = useState()
const aref = useRef(null)
const scrollRef = useRef(null)
const photo = '013bfa05b2955d0bff2823c2f3304e1838ac30801c.jpg'
const storage = getStorage()
const storageRef = ref(storage, `images/${photo}`)
const metadata = {
contentDisposition: 'inline',
contentType: 'image/jpeg'
};
useEffect(() => {
const unSub = onSnapshot(doc(db, "messages", data.chatId), (doc) => {
doc.exists() && setMessages(doc.data().messages);
});
return () => {
unSub();
};
}, [data.chatId]);
useEffect(()=>{
scrollToBottom()
}, [messages])
const sendImage = async() =>{
const uploadTask = uploadBytesResumable(storageRef, file, metadata);
await uploadTask.on(
(error) => {
console.log(error)
},
async() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
await getDownloadURL(uploadTask.snapshot.ref).then(async(downloadURL) => {
await updateDoc(doc(db, 'messages', data.chatId), {
messages: arrayUnion({photoURL: downloadURL})
})
console.log(downloadURL)
});
}
);
}
const handleChange = (e) =>{
setMsg({msg: e.target.value, origin: user.uid})
}
const sendMessage = async() =>{
if(data.chatId!='global'){
if(msg){
await updateDoc(doc(db, 'messages', data.chatId), {
messages: arrayUnion(msg)
})
}
}
if(file){
sendImage()
}
aref.current.value = ''
}
const handleFileSelect = (e) =>{
e.preventDefault()
setFile({photoURL: e.target.files[0], origin: user.uid})
}
const scrollToBottom = () =>{
scrollRef.current.scrollIntoView({behavior: 'smooth'})
}
const handleKey = (e) => {
e.code === "Enter" && sendMessage();
};
return (
<div className='chatWrapper'>
<button onClick={()=>sendImage()}>here</button>
<div className="cWrapper">
<div className="conversationProfile">
<img className='conversationImage' src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Dwayne_Johnson_2014_%28cropped%29.jpg/640px-Dwayne_Johnson_2014_%28cropped%29.jpg" alt=""/>
<span>DM Name</span>
</div>
<div className="messages">
{messages ? messages?.map((message) =>(
<div className={`message ${message.origin==user.uid && 'sender'}`}>{message.msg ? message.msg : <img className='imgMSG' referrerPolicy='no-referrer' src='https://firebasestorage.googleapis.com/v0/b/mwdims.appspot.com/o/images%2F013bfa05b2955d0bff2823c2f3304e1838ac30801c.jpg?alt=media&token=a95f8bd2-97fe-4bfa-a7d5-36772407c418"
'></img>}</div>
)) : <div className='placeHolder'>Say Something </div>}
<div ref={scrollRef} style={{visibility: 'hidden'}}></div>
</div>
<div className="chatBar">
<input ref={aref} type="text" placeholder='Type Something...' defaultValue='' onChange={handleChange} onKeyDown={handleKey}/>
<div className="chatFunctions">
<FontAwesomeIcon icon={faPaperclip} />
<input type='file' onChange={handleFileSelect}></input>
<FontAwesomeIcon icon={faImage}></FontAwesomeIcon>
<FontAwesomeIcon icon={faPaperPlane} onClick={()=>sendMessage()}/>
</div>
</div>
</div>
</div>
)
}
export default Chat

I am not succeeding in checking my input file

What check did I miss that my edit page only works if it has a file selected?
I tried to make some conditionals in the onSubmit function but I haven't found the way yet.
I know it has to do with the image array because when I click edit without selecting a file I get this error:
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
<script setup>
import { getAuth, onAuthStateChanged } from 'firebase/auth'
import {
getStorage,
uploadBytesResumable,
ref as firebaseRef,
getDownloadURL
} from 'firebase/storage'
import { doc, updateDoc, getDoc, serverTimestamp } from 'firebase/firestore'
import { db } from '../../firebase.config.js'
import { v4 as uuidv4 } from 'uuid'
const themeEditListing = ref([])
const formData = ref({
name: '',
})
const route = useRoute()
// get the theme id from the route
const themeId = route.params.id
const auth = getAuth()
onAuthStateChanged(auth, (user) => {
if (user) {
// set user on formData
formData.value.user = user.uid
} else {
navigateTo('/')
}
})
const fetchEditListing = async () => {
const docRef = doc(db, 'themes', themeId)
// response
const docSnap = await getDoc(docRef)
if (docSnap.exists) {
themeEditListing.value = docSnap.data()
formData.value = themeEditListing.value
}
}
fetchEditListing()
const onSubmit = async () => {
const newImgUrls = await Promise.all(
Array.from(formData.value.images).map((image) => {
return storeImage(image)
})
).catch((err) => {
console.log(err)
})
const imgUrls = newImgUrls ? formData.value.imgUrls.concat(newImgUrls) : formData.value.imgUrls
const formDataCopy = { ...formData.value, imgUrls, timestamp: serverTimestamp() }
delete formDataCopy.images
// update listing
// get doc reference
const docRef = doc(db, 'themes', themeId)
// update doc
await updateDoc(docRef, formDataCopy)
formData.value = { ...formData.value, imgUrls }
}
const onFileChange = (e) => {
const file = e.target.files
formData.value.images = file
}
// store images in firebase storage
const storeImage = async (image) => {
return new Promise((resolve, reject) => {
formData.value.imgUrls.push('')
newImgProgress.value = 1
const storage = getStorage()
const fileName = `${auth.currentUser.uid}-${image.name}-${uuidv4()}`
const storageRef = firebaseRef(storage, 'images/' + fileName)
const uploadTask = uploadBytesResumable(storageRef, image)
uploadTask.on(
'state_changed',
(snapshot) => {
newImgProgress.value = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('Upload is ' + newImgProgress.value + '% done')
switch (snapshot.state) {
case 'paused':
console.log('O Upload está parado')
break
case 'running':
console.log('Subindo a Imagem')
break
default:
break
}
},
(error) => {
reject(error)
},
() => {
// Handle successful uploads on complete
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
// pop the last element
formData.value.imgUrls.pop()
newImgProgress.value = 0
resolve(downloadURL)
})
}
)
})
}
</script>
<template>
<div>
<form #submit.prevent="onSubmit" class="w-full border shadow-md p-4 rounded-md">
<div>
<input
type="text"
#value="formData.name"
v-model="formData.name"
placeholder="Nome do Tema"
class="input w-full border-x-indigo-300"
/>
</div>
<div>
<input
type="file"
id="images"
#value="formData.images"
#change="onFileChange"
accept=".jpg, .png, .jpeg, .webp"
multiple
class="hidden"
/>
</label>
</div>
<button type="submit"">Edit Theme</button>
</form>
</div>
</template>
I edited the code as much as possible to make it short to read.

TypeError: ref._throwIfRoot is not a function (while trying to upload an image for Firebase Storage)

Based on the tutorial, I have exactly the same code but i am having problem while uploading the image. Every time I add the image and click upload i get an error which says :
reference.ts:290 Uncaught TypeError: ref._throwIfRoot is not a function
at uploadBytesResumable$1 (reference.ts:290:1)
at uploadBytesResumable (api.ts:164:1)
at uploadFile (AddUser.jsx:22:1)
at AddUser.jsx:49:1
at commitHookEffectListMount (react-dom.development.js:23049:1)
at commitPassiveMountOnFiber (react-dom.development.js:24816:1)
at commitPassiveMountEffects_complete (react-dom.development.js:24781:1)
at commitPassiveMountEffects_begin (react-dom.development.js:24768:1)
at commitPassiveMountEffects (react-dom.development.js:24756:1)
at flushPassiveEffectsImpl (react-dom.development.js:26990:1)
This is the code i have to add a new user with their credentials and image:
import { useEffect, useState } from 'react';
import { doc, setDoc, addDoc, collection, serverTimestamp } from "firebase/firestore";
import { createUserWithEmailAndPassword } from "firebase/auth"
import { db, auth, storage } from '../../firebase';
import { ref, uploadString, getDownloadURL, uploadBytesResumable } from "firebase/storage";
const New = ({ inputs, title }) => {
const [file, setFile] = useState("");
const [data, setData] = useState({});
useEffect(() => {
const uploadFile = () => {
const name = new Date().getTime() + file.name;
const storageRef = (storage, file.name);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
default: break;
}
},
(error) => {
console.log(error)
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setData((prev) => ({ ...prev, img: downloadURL }))
});
}
);
}
file && uploadFile();
}, [file])
const handleInput = (e) => {
const id = e.target.id;
const value = e.target.value;
setData({ ...data, [id]: value })
}
const handleAddUser = async (e) => {
e.preventDefault();
try {
const res = await createUserWithEmailAndPassword(auth, data.email, data.password);
// Add a new user in collection
await setDoc(doc(db, "users", res.user.uid), {
...data,
timeStamp: serverTimestamp()
});
} catch (err) {
console.log(err)
}
}
return (
<div className="new">
<Sidebar />
<div className="newContainer">
<Navbar />
<div className="top">
<h1 className="title">{title}</h1>
</div>
<div className="bottom">
<div className="left">
<img src={file ? URL.createObjectURL(file) : "/images/default.jpg"} alt="" />
</div>
<div className="right">
<form onSubmit={handleAddUser}>
<div className="formInput">
<label htmlFor="file">Upload Image</label>
<input type="file" id="file" onChange={(e) => setFile(e.target.files[0])} />
</div>
{inputs.map((input) => (
<div className="formInput" key={input.id}>
<label>{input.label}</label>
<input id={input.id} type={input.type} placeholder={input.placeholder} onChange={handleInput} />
</div>
))}
<button type="submit">SEND</button>
</form>
</div>
</div>
</div>
</div >
)
}
export default New
This is what I have in my firebase.js file. I have initialized firebaseConfig and all the necessary steps to upload a document to the collection. Also i have removed all the values for the firebaseConfig for security purpose.
import {
initializeApp
} from "firebase/app";
import {
getAuth
} from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth();
export const storage = getStorage(app);

Getting photo from array by path with firebase

I'm trying to show images from array by they path but getting error
App.js:44 Uncaught nc (in promise) TypeError: Cannot read properties of undefined (reading '_location')
I know that I must do something with promises, async functions etc., but I don't understand at all. So below is code example
const fireBaseApp = initializeApp(firebaseConfig);
const storage = getStorage(fireBaseApp);
function App() {
const [url, setUrl] = useState([]);
const [item, setItem] = useState([]);
const listRef = ref(storage, "/");
//getting all images from the bucket
useEffect(() => {
listAll(listRef).then((res) => {
res.items.forEach(async (item) => {
await setUrl((arr) => [...arr, item]);
});
});
}, []);
//Trying to download image from array with its' path
useEffect(() => {
const func = async () => {
const download = ref(storage, url[2]._location.path_);
await getDownloadURL(download).then((x) => {
setItem(x);
});
};
func();
}, []);
return (
<>
<img src={item} />
</>
);
}
So can anybody explain please how to do it properly. Thank you !
Add url[2] to the useEffect dependency array. But also check if it's set before running the async func. Like this:
useEffect(() => {
if(url[2]){
const func = async () => {
const download = ref(storage, url[2]._location.path_);
await getDownloadURL(download).then((x) => {
setItem(x);
});
};
func();
}
}, [url[2]]);

while trying to return firebase data to another page it passes undefined

I'm trying to fetch data from Firebase, I implemented nearly same codes like my react native app but this time I'm facing some problems that I couldn't figure out.
import {db} from './firebase'
const formatMarketData = (data) =>{
let formattedData = [];
data.forEach(item=>{
const formattedItem = {
...item
}
formattedData.push(formattedItem);
});
return formattedData;
}
export const FirebaseService = async (id) => {
id=id.replace(/['"]+/g, "");
const historyKey="/coins/0/"+id
await
db.ref(historyKey)
.once('value')
.then(snapshot => {
const data = snapshot.val();
const formattedResponse= formatMarketData(data);
console.log(formattedResponse)
return formattedResponse
});
};
This function helps me to retrieve data from my firebase rtdb. The console.log functions works and writes as expected but when I'm trying to catch it in my News page it becomes undefined.
import React from 'react'
import { useState,useEffect } from 'react'
import { FirebaseService } from '../../Services/FirebaseService'
const NewList = ({id}) => {
const [data,setData] = useState([])
useEffect(()=>{
console.log(id)
const fetchMarketData = async () =>{
const marketData = await FirebaseService(id);
return setData(marketData);
}
fetchMarketData();
return () => {
}
},[])
return (
<div>
{data!==undefined?data.map((d)=>{return(<p>{d.id}</p>)})
:<p>no data yet</p>}
</div>
)
}
export default NewList
I'm missing something but I can't notice. Another view might be helpful.
Define formattedResponse at start of function and return it at very end.
I have edited you function
import {db} from './firebase'
const formatMarketData = (data) =>{
let formattedData = [];
data.forEach(item=>{
const formattedItem = {
...item
}
formattedData.push(formattedItem);
});
return formattedData;
}
export const FirebaseService = (id) =>{
let formattedResponse = [];
id=id.replace(/['"]+/g, "");
const historyKey="/coins/0/"+id
await
db.ref(historyKey)
.once('value')
.then(snapshot => {
const data = snapshot.val();
formattedResponse=
formatMarketData(data);
console.log(formattedResponse)
})
return formattedResponse
};

Categories

Resources