Search code examples
reactjsfirebasegoogle-cloud-firestoreuse-effectuse-state

How to display a badge when a chat thread has unread messages React JS, Firestore


I am developing a chat application in React and firebase firestore. I want to display an unread messages badge every time a new message is added to the database. Currently, I am using a useEffect hook to check if the last message is read, and that only works only the first time the page renders - the unread messages badge appears only after I reload the page. I think what I can't figure out is how to re-render every time the state changes. Kindly look at my code and tell me what I am missing. I hope my issue is clear. Thanks in advance.

const [chatMessages, setChatMessages] = useState([])
const [isRead, setIsRead] = useState(false)

const readsRef = db.collection('rooms').doc(id).collection('messages')

useEffect(() => {

    const unsubscribe = readsRef.orderBy('timestamp', 'desc')

        .limit(1).onSnapshot((snapshot) => {
            snapshot.docs.map((snap) => {
                setChatMessages(snap.data().message)

                 readsRef.doc(snap.id).collection('read').doc(userID.uid).onSnapshot((snapshot1 => {
                    if (snapshot1.get('readReceipt') === userID.uid) {
                        setIsRead(true)
   
                    }
            
                }))

            })

    })
    return unsubscribe;
    
}, [isRead])


 return (

 <SidebarOptionChannel>

                   
    <span># </span>{title} - {chatMessages}<span>{isRead ? null : <UnreadBadge> 
    <span>1</span></UnreadBadge>  }</span>

  </SidebarOptionChannel>
 )

Solution

  • Another solution to your problem could be to update your chat application by listening for changes in your Database of Firebase. This can be done by using the methods of firebase.database.Reference:

    on() or once()

    Here is an example provided by the documentation of Firebase:

    var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
    starCountRef.on('value', (snapshot) => {
      const data = snapshot.val();
      updateStarCount(postElement, data);
    });