React useState object not letting me access it's properties

Viewed 55

I'm making a chat app and I'm trying to create dynamic chat pages based on room page names within firestore. My chat component updates the chatbox title depending on what it finds off of firestore. I have determined that the query I'm using does in fact pull the data correctly through console.log.

function Chat() {
  const { roomId } = useParams();

  const [roomDetails, setRoomDetails] = useState();

  useEffect(() => {
    const roomQuery = query(
      collection(db, "rooms"),
      where("name", "==", roomId)
    );
    if (roomId) {
      const unsubscribe = onSnapshot(roomQuery, (snapshot) => {
        setRoomDetails(snapshot.docs.map((doc) => ({ ...doc.data() })));
      });
      return () => {
        unsubscribe();
      };
    }
  }, [roomId]);

  console.log(roomDetails);

  return (
    <div className="chat">
      <div className="chat__header">
        <div className="chat__headerLeft">
          <h4 className="chat__channelName">
            <strong>#{roomDetails?.name}</strong>
            <StarBorderOutlinedIcon />
          </h4>
        </div>
        <div className="chat__headerRight">
          <p>
            <InfoOutlinedIcon /> Details
          </p>
        </div>
      </div>
    </div>
  );
}

What doesn't work is the bottom section

<h4 className="chat__channelName">
  <strong>#{roomDetails?.name}</strong>
  <StarBorderOutlinedIcon />
</h4>

Within my browser the chat title will be blank and I presume that it's because it isn't reading the data or the data isn't defined yet. Here is what the useState looks like in console.

console.log output

    [{…}]0: 
      {name: 'general'}
      length: 1
      [[Prototype]]: Array(0)

Here's what Firestore looks like Firestore data/schema

2 Answers

This will turn your state roomDetails into an array:

setRoomDetails(snapshot.docs.map((doc) => ({ ...doc.data() }))); 

And array doesn't have property name in it, so roomDetails?.name returns undefined. You need to access like this:

<strong>#{roomDetails?[0].name}</strong>

This should give you the UI output.

I found the solution I changed the way the Data was updated into the useState

useEffect(() => {
  const roomQuery = query(
    collection(db, "rooms"),
    where("name", "==", roomId)
  );
  if (roomId) {
    const unsubscribe = onSnapshot(roomQuery, (snapshot) => {
      setRoomDetails(snapshot.docs.at(0).data());
    });
    return () => {
      unsubscribe();
    };
  }
}, [roomId]);

The way the data is rendered is the same. Hope this helps some future people.

Related