在React.js应用上从firebase中获取和显示图片。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在React.js应用上从firebase中获取和显示图片。相关的知识,希望对你有一定的参考价值。
所以我试图从Firebase存储中获取图片,然后在React组件中显示它们。坦率地说,我是Reactjavascript的新手,我很难理解ReactJS的异步性,我遇到的问题是,我的图片被获取了,但组件没有在获取完成后重新渲染......
这是我主页面上的代码,在useEffect函数中,我试图获取图片,然后将它们的下载URL存储在一个数组中,然后将该数组设置为状态(在页面加载时,即只有一次)。由于这些都是承诺,所以它不是同步发生的,当我第一次加载页面时,它没有显示任何图片。然而,如果我点击页面上的其他组件,它就会重新渲染我的Pictures组件,并且图像会出现(??),所以我知道取图成功了。
let storageRef = firebase.storage().ref()
let calendarRef = React.createRef()
const position = props.location.state.name.indexOf("@")
const username = props.location.state.name.substring(0, position);
const [simpleDate, setSimpleDate] = useState(null)
const [selectedDate, setSelectedDate] = useState('')
const [showModal, setShowModal] = useState(false)
const [showCancelModal, setShowCancelModal] = useState(false)
const [expectedPeople, setExpectedPeople] = useState(null)
const [events, setEvents] = useState([])
const [helpModal, showHelpModal] = useState(false)
const [pictureURLs, setPictureURLs] = useState([])
useEffect(() =>
//load pictures
const fetchImages = async () =>
let urls = []
storageRef.child('cabinPictures').listAll().then((result) =>
result.items.forEach((imageRef) =>
imageRef.getDownloadURL().then(url =>
urls.push(url)
)
)
)
return urls;
fetchImages().then(urls =>
setPictureURLs(urls);
console.log("inside .then() " + pictureURLs)
)
//fetch reservations
firebase
.firestore()
.collection('reservations')
.onSnapshot(serverUpdate =>
const reservations = serverUpdate.docs.map(_doc =>
const data = _doc.data();
data['id'] = _doc.id;
return data;
);
let fetchedEvents = reservations.map(reservation =>
let date = reservation.reservationDate.toDate()
const month = ("0" + (date.getUTCMonth() + 1))
let dateString = date.getUTCFullYear() + "-" + ("0" + (date.getUTCMonth()+1)).slice(-2) + "-" + ("0" + date.getUTCDate()).slice(-2)
return title: reservation.username + " - " + reservation.numPeople + " total", date: dateString, id: reservation.id, totalPeople: reservation.numPeople, month: month
)
console.log(fetchedEvents)
setEvents(fetchedEvents)
);
, [])
我的Pictures组件在主页面中的使用效果(上图)运行。我把state中的urls作为一个道具传递过来。
<div className="pictures-div-container">
<Pictures pictureURLs=pictureURLs>
</Pictures>
</div>
我的Picture组件的代码
import React, useState, useEffect from 'react'
import styles from "./styles.css"
const firebase = require('firebase');
const Pictures = (props) =>
const [uploadImage, setUploadImage] = useState(null)
const [progressValue, setProgressValue] = useState(0)
let storageRef = firebase.storage().ref()
let pictureURLs = props
const handleUpload = () =>
setProgressValue(0)
const uploadTask = storageRef.child(`cabinPictures/$uploadImage.name`).put(uploadImage)
uploadTask.on('state_changed',
(snapshot) =>
//progress function
const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes ) * 100)
setProgressValue(progress)
,
(error) =>
//error function
console.log(error)
,
() =>
//complete function
storageRef.child('cabinPictures').child(uploadImage.name).getDownloadURL().then(url =>
console.log(url)
)
);
const handleFileSelect = (e) =>
if (e.target.files[0])
setUploadImage(e.target.files[0])
return (
<div className="pictures-container">
<h2>Upload a Picture!</h2>
<button className="upload-button" onClick=() => handleUpload()>Upload</button>
<input type="file" onChange=(e) => handleFileSelect(e)></input>
<progress value=progressValue max="100"></progress>
<div className="pictures">
pictureURLs.map((url, index) =>
return <img className="picture" key=index src=url></img>
)
</div>
</div>
)
export default Pictures
那么,谁能帮我理解一下,为什么Pictures组件在从firebase获取图片urls后,当状态被设置时,不会自动重新渲染?我以为当一个组件中的道具发生变化时,整个组件都会重新渲染?
EDIT:于是我就按照答案的建议修改了我的主页面的useEffect函数,果然成功了!
//fetch and load pictures
const fetchImages = async () =>
let result = await storageRef.child('cabinPictures').listAll();
let urlPromises = result.items.map(imageRef => imageRef.getDownloadURL())
return Promise.all(urlPromises)
const loadImages = async () =>
const urls = await fetchImages()
setPictureURLs(urls)
loadImages()
你必须让所有的嵌套承诺解决之前,你必须让所有的承诺解决。return urls
我对firebase的API不是很了解,所以不确定是否会有 result.items
是一个实际的数组或一个有foreach方法的对象。如果它是一个js数组,下面的代码应该是有效的
试试这样的事情。
//load pictures
const fetchImages = async() =>
let result = await storageRef.child('cabinPictures').listAll();
/// map() array of the imageRef.getDownloadURL() promises
let urlPromises = result.items.map(imageRef => imageRef.getDownloadURL());
// return all resolved promises
return Promise.all(urlPromises);
const urls = await fetchImages()
setPictureURLs(urls);
console.log("inside .then() ", urls)
以上是关于在React.js应用上从firebase中获取和显示图片。的主要内容,如果未能解决你的问题,请参考以下文章
React JS App 与 Firebase 远程配置以获取远程标志
是否有使用 react.js 和 firebase 的简单 CRUD 示例应用程序?
如何从 React JS 中的 firebase 文档的所有子集合中获取数据? [复制]