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...
 
Ad

Advertisements

Joined
Jan 30, 2023
Messages
71
Reaction score
2
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,
      });
 

Top