如何将聊天中的加载图像替换为使用 ReactJS 上传到 Firebase 存储的图像?
Posted
技术标签:
【中文标题】如何将聊天中的加载图像替换为使用 ReactJS 上传到 Firebase 存储的图像?【英文标题】:How to replace a loading image in a chat with an image uploaded to Firebase Storage using ReactJS? 【发布时间】:2021-04-09 23:59:00 【问题描述】:我已经使用 Firebase 和 ReactJS 建立了一个聊天室。我主要关注他们的 Firebase 的网络代码实验室 https://firebase.google.com/codelabs/firebase-web#1。但是,我一直卡在图像上传功能上。由于我使用的是 ReactJS,我不得不修改他们的纯 JS 代码以匹配我的。我能够在 Firestore 中保存带有“正在加载”图像 url 的消息,然后,我成功地保存了我想最终在 Firebase 存储中的聊天中显示的图像,最后我成功地从存储中检索了它的 url 并替换它使用 Firestore 中加载图像的 url。该图像确实显示在聊天中,但是,加载图像实际上并未被替换,而是当我希望它被完全替换时,它仍保留在聊天中,显然,因此加载图像不再存在。这就是我的意思,在这张图片中:
如您所见,顶部的加载图像保持不变,而不是被其下方的图像替换。我认为在我使用新图像 url 保存新快照之前,应该以某种方式将其过滤掉。但是,我无法弄清楚如何正确地做到这一点。我试图根据本地保存的加载图像的 url 将其过滤掉,但由于它在 Storage 中保存为 base64,所以它不起作用。也没有使用实际的 Base64 代码来过滤掉它。所以,我需要帮助来解决这个问题。 codelab 并没有真正指定这一点,也不清楚他们是如何在纯 javascript 的代码中做到这一点的,我使用 ReactJS,所以它可能不是 100% 合适的。
我相信,这里有足够的代码来查看发生了什么。如果您需要更多,请告诉我。
以下是我将图像发送到 Chat 的方式:(以 Firebase 代码实验室为模型)
sendImageToChat ()
this.state.chatFiles.forEach((file) =>
firebase.firestore().collection('Chats')
.doc(this.state.uid)
.collection('Messages')
.add(
docId: this.state.docId,
imageUrl: loadingLogo,
timestamp: new Date(),
uid: this.state.uid,
name: this.state.displayName,
email: this.state.email
)
.catch((error) =>
this.setState( writeError: error.message );
)
.then((messageRef) =>
// 2 - Upload the image to Cloud Storage.
const filePath = `users/$this.state.displayName/$this.state.uid/$moment().format("MMM Do YY")/$uuidv4()/$file.name`
return firebase.storage().ref(filePath).put(file).then((fileSnapshot) =>
// 3 - Generate a public URL for the file.
return fileSnapshot.ref.getDownloadURL().then((url) =>
// 4 - Update the chat message placeholder with the image's URL.
return messageRef.update(
imageUrl: url,
storageUri: fileSnapshot.metadata.fullPath
);
);
);
).catch(function(error)
console.error('There was an error uploading a file to Cloud Storage:', error);
);
)
this.setState(
chatFiles: []
)
document.getElementById('file-1').value = "";
下面是我如何在添加加载图像以及修改其 url 时 setState上面解释的原因)。
startChat ()
document.getElementById("myForm").style.display = "block";
const ref = firebase.firestore().collection('Chats').doc(this.state.uid).collection('Messages');
const query = ref.orderBy('timestamp', 'desc').limit(10)
this.unsubFromMessages = query.onSnapshot((snapshot) =>
if (snapshot.empty)
console.log('No matching documents.');
firebase.firestore().collection('Chats').doc(this.state.uid).
set(
name: this.state.displayName,
uid: this.state.uid,
email: this.state.email
).then(console.log("info saved"))
.catch((error) =>
console.log("Error saving info to document: ", error);
);
snapshot.docChanges().reverse().forEach((change) =>
if (change.type === 'removed')
console.log(change.doc.data().content)
else if (change.type === 'added')
this.setState(state =>
const messages = [...state.messages, id: change.doc.id, body: change.doc.data()]
return
messages
)
setTimeout( this.scrollToBottom(), 2000)
else if (change.type === 'modified')
const filteredMessages = this.state.messages.filter(message => message.imageUrl !== loadingLogo)
console.log(filteredMessages)
this.setState(state =>
const messages = [...filteredMessages, id: change.doc.id, body: change.doc.data()]
return
messages
)
setTimeout( this.scrollToBottom(), 2000)
);
, (error) => console.log(error));
这是 Chat 的 JSX 的一部分:
<div className="chatArea" id='messages'>
this.state.messages.map((message, index) =>
return message.body.uid === this.state.uid
?
<div>
message.body.imageUrl ?
<img src=message.body.imageUrl className="message-sent"></img>
:
<p className="message-sent" key=index>message.body.content</p>
</div>
:
<p className="message-received" key=index>message.body.content</p>
)
<div style= float:"left", clear: "both"
ref=(el) => this.myRef = el; >
</div>
</div>
我知道问题不在于 Firebase,而在于 ReactJS。我知道我需要在使用新 url 的修改消息保存到状态之前或之后删除、过滤、替换或删除加载图像。所以,请帮我解决这个问题。相信很多人都会遇到这个问题。
谢谢!
【问题讨论】:
【参考方案1】:我想通了。我不妨删除这个问题,但它可能会帮助某人建立与 ReactJS 和 Firebase 的聊天。无论如何,我根据对象属性过滤掉的方法 imageUrl 是一个可行的选择。有用!我愚蠢的疏忽是我没有在对象“消息”之后添加父属性或对象“body”。更具体地说,应该是 const filtersMessages = this.state.messages.filter(message => message. body.imageUrl !== loadingLogo)。您还可以尝试添加一个对象属性,您可以使用该属性来过滤掉消息,例如,允许:是或否。如果您需要更多说明,请问我,我很乐意提供帮助。编码愉快!
【讨论】:
以上是关于如何将聊天中的加载图像替换为使用 ReactJS 上传到 Firebase 存储的图像?的主要内容,如果未能解决你的问题,请参考以下文章
reactjs - 如何隐藏一个div并将其替换为reactjs中的另一个div?