skip to Main Content

I’m trying to add a feature to my chat app to allow the user to go back to chat rooms they recently visited, and created a message in. Right now I’m just trying to display names the chat rooms on the page.

my firebase date base is structured like this.

-ChatRooms(collection)
  -"chat room name" (document)
  -room(name of chat room)
  -uid
    -messages(subcollection)
      -created
      -room(name of chat room)
      -text
      -uid
      -user(display name)
      -userPic

I’m trying to get inside the "messages" subcollection, so I can query it to only display the names of the chat Rooms the user has visited. If the "uid" of the document inside the messages subCollection matches the "uid" of firebase "auth" currentUser.uid.

this is my code.

 const [chatRoomData, setChatRoomData] = useState([]);
 const [firebaseUserInfo, setFirebaseUserInfo] = useState(auth.currentUser);


  useEffect(() =>{
    onAuthStateChanged(auth, currentUser => {
      setFirebaseUserInfo(currentUser);
      const chatRoomCollectionRef = collection(dataBase, "ChatRooms/room/messages");
      console.log(chatRoomCollectionRef)
      const queryChatRooms = query(chatRoomCollectionRef, where("uid", "==", currentUser.uid));
      const unSubscribe = onSnapshot(queryChatRooms, (snapshot) => {
        const chatRooms = [];
        snapshot.forEach((doc) => {
          chatRooms.push({...doc.data(), id: doc.id});
        });
        setChatRoomData(chatRooms);
      })
      return () => unSubscribe();
    })
  }, []);

  return (
    <>
        <div className="chats-container">
          <header className='header-container'> 
            <h1 className="header">Your Chats</h1>
          </header>
          {chatRoomData.map((data) =>(
            <div className='users-chatRooms-container' key={data.id}>
              <button className='users-chatRooms'>{data.chatRoom}</button>
            </div>
          ))}
        </div>
    </>
  );
}  

I tried this and nothing displays on the page. What is wrong with my code?

2

Answers


  1. you need to reference each "room" document and then access its "messages" subcollection. Also, make sure you’re using the correct field names. Try the following code:

    import { useState, useEffect } from 'react';
    import { onAuthStateChanged } from 'firebase/auth';
    import {
      collection,
      query,
      where,
      getDocs,
      onSnapshot,
    } from 'firebase/firestore';
    import { auth, dataBase } from 'your-firebase-config-file'; 
     // Import your Firebase configuration
    
    function YourComponent() {
      const [chatRoomData, setChatRoomData] = useState([]);
      const [firebaseUserInfo, setFirebaseUserInfo] = useState(auth.currentUser);
    
      useEffect(() => {
        onAuthStateChanged(auth, (currentUser) => {
          setFirebaseUserInfo(currentUser);
    
          const chatRoomCollectionRef = collection(dataBase, 'ChatRooms');
          const queryChatRooms = query(chatRoomCollectionRef, where('uid', '==', currentUser.uid));
    
          const unSubscribe = onSnapshot(queryChatRooms, (snapshot) => {
            const chatRooms = [];
            snapshot.forEach(async (doc) => {
              const messagesQuerySnapshot = await getDocs(collection(doc.ref, 'messages'));
              messagesQuerySnapshot.forEach((messageDoc) => {
                chatRooms.push({
                  chatRoom: messageDoc.data().room,
                  id: messageDoc.id,
                });
              });
            });
            setChatRoomData(chatRooms);
          });
    
          return () => unSubscribe();
        });
      }, []);
    
      return (
        <>
          <div className="chats-container">
            <header className="header-container">
              <h1 className="header">Your Chats</h1>
            </header>
            {chatRoomData.map((data) => (
              <div className="users-chatRooms-container" key={data.id}>
                <button className="users-chatRooms">{data.chatRoom}</button>
              </div>
            ))}
          </div>
        </>
      );
    }
    
    export default YourComponent;
    

    Make sure to adjust the import statements according the firbease. Ask if you’ve any doubts.

    Login or Signup to reply.
  2. Here’s the best example I can do without seeing the data

    import { useEffect, useState } from 'react';
    import { onAuthStateChanged } from 'firebase/auth';
    import { collection, query, where, onSnapshot } from 'firebase/firestore';
    import { auth, dataBase } from 'your-firebase-config'; // Replace with your actual Firebase configuration
    
    const YourComponent = () => {
      const [chatRoomData, setChatRoomData] = useState([]);
      const [firebaseUserInfo, setFirebaseUserInfo] = useState(auth.currentUser);
    
      useEffect(() => {
        onAuthStateChanged(auth, (currentUser) => {
          if (currentUser) {
            setFirebaseUserInfo(currentUser);
    
            const messagesCollectionRef = collection(dataBase, "ChatRooms"); // Assuming "ChatRooms" is your collection
            const queryChatRooms = query(messagesCollectionRef, where("uid", "==", currentUser.uid));
    
            const unSubscribe = onSnapshot(queryChatRooms, (snapshot) => {
              const chatRooms = [];
              snapshot.forEach((doc) => {
                const messagesSubcollectionRef = collection(doc.ref, "messages");
                const queryMessages = query(messagesSubcollectionRef, where("uid", "==", currentUser.uid));
    
                onSnapshot(queryMessages, (messagesSnapshot) => {
                  messagesSnapshot.forEach((messageDoc) => {
                    chatRooms.push({ chatRoom: messageDoc.data().room, id: messageDoc.id });
                  });
    
                  setChatRoomData(chatRooms);
                });
              });
            });
    
            return () => unSubscribe();
          }
        });
      }, []);
    
      return (
        <>
          <div className="chats-container">
            <header className="header-container">
              <h1 className="header">Your Chats</h1>
            </header>
            {chatRoomData.map((data) => (
              <div className="users-chatRooms-container" key={data.id}>
                <button className="users-chatRooms">{data.chatRoom}</button>
              </div>
            ))}
          </div>
        </>
      );
    };
    
    export default YourComponent;
    
    

    Make sure to replace ‘your-firebase-config’ with your actual Firebase configuration. If this doesn’t solve the issue, consider checking your Firestore structure and adjust the code accordingly.

    OR if the issue is just printing the nexted obj

    You can solve this with recursion, here’. an example:

    const RecursivePrint = ({ data }) => {
      return (
        <div>
          {Object.keys(data).map((key) => {
            const value = data[key];
    
            if (typeof value === 'object' && value !== null) {
              return (
                <div key={key}>
                  <strong>{key}:</strong>
                  <RecursivePrint data={value} />
                </div>
              );
            } else {
              return (
                <div key={key}>
                  <strong>{key}:</strong> {value}
                </div>
              );
            }
          })}
        </div>
      );
    };
    
    // Example usage:
    const data = {
      name: 'John Doe',
      age: 30,
      address: {
        street: '123 Main St',
        city: 'Cityville',
      },
    };
    
    const App = () => {
      return (
        <div>
          <h1>Recursive Print Example</h1>
          <RecursivePrint data={data} />
        </div>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search