如何将聊天中的加载图像替换为使用 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中的json响应字段加载图像

reactjs - 如何隐藏一个div并将其替换为reactjs中的另一个div?

使用 ReactJS 动态加载本地图像

如何显示缓冲图像

从 Promise(ReactJS 和 Axios)中提取图像数据

如何在 ReactJS 中做动态图像?