user10242552
user10242552

Reputation:

How to make uploading pictures and sending messages together (React & Firebase)?

I am a newcomer to React development. The function I currently want to achieve is to allow users to send uploaded pictures. This function is similar to messenger uploading pictures and can be sent together with text. The following is my current code:

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.log(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;

Because the picture is stored in firebase-storage, and the message sent by the user is stored in firestore. I don't know how to connect the two of them. I hope someone can provide answers and suggestions on the code will be better.

Upvotes: 2

Views: 1541

Answers (2)

Gayatri Dipali
Gayatri Dipali

Reputation: 1283

  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}
            />
           ))
         }
    )

As your storing the imageUrl in firestore you don't have to look up to your storage anymore as the url is going to remain the same. That's why I am using the url that is stored in the firestore.

You can create your own message component.

Upvotes: 1

Doug Stevenson
Doug Stevenson

Reputation: 317497

Typically you store the path of the file in storage, or download URL (or both), as fields in the related document. This typically assumes that you upload to storage first, then write the document. But you could always update the document after the upload completes.

Some people also use the same randomly generated ID of the document as the name of the file in storage, so you always know how to get from one to other.

Upvotes: 1

Related Questions