Как сделать загрузку изображений и отправку сообщений вместе (React и Firebase)?

Я новичок в разработке React. В настоящее время я хочу добиться того, чтобы пользователи могли отправлять загруженные изображения. Эта функция аналогична загрузке картинок в мессенджере и может быть отправлена ​​вместе с текстом. Ниже приведен мой текущий код:

import React, { useState } from 'react'
import "./ChatInput.css"
import { useStateValue } from './StateProvider';
import db from './firebase';
import firebase from 'firebase';
import { storage } from './firebase';

function ChatInput({channelName, channelId}) {
    const [input, setInput] = useState("");
    const [{user}] = useStateValue();
    const [image, setImage] = useState(null);
    const [imageUrl, setImageUrl] = useState("");
    const sendMessage = (e) => {
        e.preventDefault();

        if (channelId){
            db.collection('courses').doc(channelId).collection('messages').add({
            message:input,
            timestamp:firebase.firestore.FieldValue.serverTimestamp(),
            user:user.displayName,
            userImage: user.photoURL,

        });
    }
    setInput(""); 
    };

    const fileSelectedHandler = e => {
        if (e.target.files[0]) {
            setImage(e.target.files[0]);
        }
    };
    
    const fileUploadedHandler = () => {
        const uploadTask = storage.ref(`images/${image.name}`).put(image);
        uploadTask.on(
            "state_changed",
            snapshot => {},
            error => {
                console.info(error);
            },
            () => {
                storage
                    .ref("images")
                    .child(image.name)
                    .getDownloadURL()
                    .then(url => {
                        setImageUrl(url)
                    });
            }
        );
    }


    
    return (
        <div className  = "chatInput">
            <form>
                <input
                value  = {input}
                onChange = {(e)=>setInput(e.target.value)} 
                placeholder = {`Message #${channelName?.toLowerCase()}`} />
                <button type = "submit" onClick = {sendMessage}>SEND</button>

                
            </form>
            <input type = "file" onChange = {fileSelectedHandler}/>
            <button type = "submit" onClick = {fileUploadedHandler}>UPLOAD</button>
            <br />
            <img src = {imageUrl} alt = "" />
        </div>
    );
}

export default ChatInput;

Потому что картинка хранится в firebase-storage, а сообщение, отправленное пользователем, хранится в firestore. Я не знаю, как соединить их двоих. Я надеюсь, что кто-то может дать ответы и предложения по коду будет лучше.

🤔 А знаете ли вы, что...
С React можно легко интегрировать с другими библиотеками и фреймворками.


1
973
2

Ответы:

Обычно вы сохраняете путь к файлу в хранилище или URL-адрес загрузки (или и то, и другое) в качестве полей в соответствующем документе. Обычно это предполагает, что вы сначала загружаете в хранилище, а затем пишете документ. Но вы всегда можете обновить документ после завершения загрузки.

Некоторые люди также используют тот же случайно сгенерированный идентификатор документа, что и имя файла в хранилище, поэтому вы всегда знаете, как перейти от одного к другому.


Решено
  const [messages, setMessages] = useState([]);
  useEffect(()=>{
        db
        .collection('courses')
        .doc(channelId)
        .collection('messages')
        .orderBy("timestamp","desc")
        .onSnapshot((snapshot)=>
           setMessages(
             snapshot.docs.map((doc)=>({
              id: doc.id,
              data: doc.data()
         }))
        )
      )
    },[]);

    return(
       {
         messages.map(({id,data:{content,user,timestamp,userImage}})=>(
           <Message  
             message = {content} 
             user = {user}
             id = {id}
             key = {id}
             createdAt = {timestamp}
             senderImgSrc = {userImage}
            />
           ))
         }
    )

Поскольку вы храните imageUrl в firestore, вам больше не нужно искать свое хранилище, поскольку URL-адрес останется прежним. Вот почему я использую URL-адрес, который хранится в хранилище огня.

Вы можете создать свой собственный компонент сообщения.