首页 > 解决方案 > 如何将聊天中的加载图像替换为使用 ReactJS 上传到 Firebase 存储的图像?

问题描述

我已经使用 Firebase 和 ReactJS 建立了一个聊天室。我主要在https://firebase.google.com/codelabs/firebase-web#1关注他们的 Firebase 网络代码实验室. 但是,我一直卡在图像上传功能上。由于我使用的是 ReactJS,我不得不修改他们的纯 JS 代码以匹配我的。我能够在 Firestore 中保存带有“正在加载”图像 url 的消息,然后,我成功地保存了我想最终在 Firebase 存储中的聊天中显示的图像,最后我成功地从存储中检索了它的 url 并替换它使用 Firestore 中加载图像的 url。该图像确实显示在聊天中,但是,加载图像实际上并未被替换,而是当我希望它被完全替换时,它仍保留在聊天中,显然,因此加载图像不再存在。这就是我的意思,在这张图片中:

在此处输入图像描述

如您所见,顶部的加载图像保持不变,而不是被其下方的图像替换。我认为在我使用新图像 url 保存新快照之前,应该以某种方式将其过滤掉。但是,我无法弄清楚如何正确地做到这一点。我试图根据本地保存的加载图像的 url 将其过滤掉,但由于它在 Storage 中保存为 base64,所以它不起作用。也没有使用实际的 Base64 代码来过滤掉它。所以,我需要帮助来解决这个问题。codelab 并没有真正指定这一点,也不清楚他们是如何在纯 Javascript 代码中做到这一点的,而且我使用 ReactJS,所以它可能不是 100% 合适的。

我相信,这里有足够的代码来查看发生了什么。如果您需要更多,请告诉我。

以下是我将图像发送到聊天室的方式:(以 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 时设置状态:(注意我如何尝试过滤掉加载图像的 loadingLogo 状态,但由于解释的原因,它显然不起作用多于)。

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 的修改消息保存到状态之前或之后删除、过滤、替换或删除加载图像。所以,请帮我解决这个问题。相信很多人都会遇到这个问题。

谢谢!

标签: reactjsfirebase

解决方案


我想到了。我不妨删除这个问题,但它可能会帮助某人与 ReactJS 和 Firebase 建立聊天。无论如何,我根据对象属性过滤掉的方法 imageUrl 是一个可行的选择。有用!我愚蠢的疏忽是我没有在对象“消息”之后添加父属性或对象“body”。更具体地说,应该是 const filtersMessages = this.state.messages.filter(message => message.body.imageUrl 而不是 const filteredMessages = this.state.messages.filter(message => message.imageUrl !== loadingLogo ) !== loadingLogo)。您还可以尝试添加一个对象属性,您可以使用它来过滤掉消息,例如,允许:是或否。如果您需要更多说明,请问我,我很乐意提供帮助。快乐编码!


推荐阅读