Messages don't show on the website, only stores in Firestore Database

Joined
Jan 22, 2023
Messages
1
Reaction score
0
When I send a message, it doesn't display on the website, it only stores in Firestore. I changed the rules and indexes, I'll type here the essential parts of my code which may cause this to happen.
MainPage.jsx:
Code:
import React, { useEffect, useRef, useState } from "react";
import {
  query,
  collection,
  orderBy,
  onSnapshot,
  limit,
  where,
} from "firebase/firestore";
import { db } from "../components/base";
import Chat from "../pages/Chat";
import SendMessage from "../pages/SendMessage";
import { useNavigate } from "react-router-dom";

const MainPage = () => {
  const [messages, setMessages] = useState([]);
  const scroll = useRef();
  let navigate = useNavigate();
  const [userIdToken, setUserIdToken] = useState(
    sessionStorage.getItem("ID Token")
  );

  const handleLogout = () => {
    sessionStorage.removeItem("Auth Token");
    sessionStorage.removeItem("ID Token");
    navigate("/");
  };
  useEffect(() => {
    setUserIdToken(sessionStorage.getItem("ID Token"));
  }, []);
  useEffect(() => {
    if (userIdToken) {
      const q = query(
        collection(db, "messages"),
        where("userIdToken", "==", userIdToken),
        orderBy("createdAt"),
        limit(50)
      );
      const unsubscribe = onSnapshot(q, (QuerySnapshot) => {
        let messages = [];
        QuerySnapshot.forEach((doc) => {
          messages.push({ ...doc.data(), id: doc.id });
        });
        setMessages(messages);
      });
      return () => unsubscribe;
    }
  }, [userIdToken]);

  const handleSendMessage = (data) => {
    const user = auth.currentUser;
    if (user) {
      db.collection("messages").add({
        ...data,
        name: user.displayName,
        avatar: user.photoURL,
        createdAt: new Date(),
        userId: user.uid,
        userIdToken: userIdToken,
      });
      setMessages([
        ...messages,
        {
          ...data,
          createdAt: new Date(),
          userId: user.uid,
          userIdToken: userIdToken,
        },
      ]);
    }
  };

  return (
    <main className="chat-box">
      <div className="messages-wrapper">
        {messages.map((message) => (
          <Chat key={message.id} message={message} />
        ))}
      </div>
      <span ref={scroll}></span>
      <SendMessage scroll={scroll} onSendMessage={handleSendMessage} />
      <button onClick={handleLogout}>Logout</button>
    </main>
  );
};

export default MainPage;

SendMessage.jsx:
Code:
import React, { useState } from "react";
import { auth, db } from "../components/base";
import { addDoc, collection, serverTimestamp } from "firebase/firestore";

const SendMessage = ({ scroll }) => {
  const [message, setMessage] = useState("");

  const sendMessage = async (event) => {
    event.preventDefault();
    if (message.trim() === "") {
      alert("Enter valid message");
      return;
    }
    const { uid, displayName, photoURL } = auth.currentUser;
    await addDoc(collection(db, "messages"), {
      text: message,
      name: displayName,
      avatar: photoURL,
      createdAt: serverTimestamp(),
      uid,
    });
    setMessage("");
    scroll.current.scrollIntoView({ behavior: "smooth" });
  };
  return (
    <form onSubmit={(event) => sendMessage(event)} className="send-message">
      <label htmlFor="messageInput" hidden>
        Enter Message
      </label>
      <input
      style={{marginLeft: '100px'}}
        id="messageInput"
        name="messageInput"
        type="text"
        className="form-input__input"
        placeholder="type message..."
        value={message}
        onChange={(e) => setMessage(e.target.value)}
      />
      <button type="submit">Send</button>
    </form>
  );
};

export default SendMessage;

Chat.jsx:
Code:
Chat.jsx:import React from "react";
import './Chat.css';

const Chat = ({ message }) => {
  const timestamp = new Date(message.createdAt).toLocaleString();
  return (
    <div>
      <div className="chat-bubble__right">
        <p className="user-name">{message.name}</p>
        <p className="user-message">{message.text}</p>
        <p className="timestamp">{new Date(message.createdAt).toLocaleString()}</p>
      </div>
    </div>
  );
};

export default Chat;
Cloud Firestore rules:
Code:
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if true;
      allow write: if request.auth.uid != null;
    }
  }
}
Cloud Firestore indexes:
Code:
Collection ID   Fields indexed
Query scope     Status 
messages    userIdToken Ascending createdAt Ascending __name__ Ascending    Collection      Enabled

So when a user types a message, it should display on the website and store in Firestore Database, in my case, it only stores in Firestore.
I've no clue what causes this issue...
 
Joined
Jan 30, 2023
Messages
107
Reaction score
13
The problem is with the line in MainPage.jsx:

YAML:
setMessages([
        ...messages,
        {
          ...data,
          createdAt: new Date(),
          userId: user.uid,
          userIdToken: userIdToken,
        },
      ]);

This line of code updates the state of the component with the latest message, but it won't reflect in real-time on the Firestore database. To fix this, you should call the Firestore add method, just like in SendMessage.jsx:

PHP:
db.collection("messages").add({
        ...data,
        name: user.displayName,
        avatar: user.photoURL,
        createdAt: new Date(),
        userId: user.uid,
        userIdToken: userIdToken,
      });
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,630
Members
45,335
Latest member
Tommiesal

Latest Threads

Top