Search code examples
javascriptreact-nativegoogle-cloud-firestorereact-native-gifted-chat

Why are chat messages from firestore showing up in "groups"?


I am trying to use react-native-gifted-chat to build a chat room in my app.

Unfortunately, the chat's are appearing in "groups", not sequentially. For example,

  1. I send a message
  2. Someone else sends a message
  3. I send another message
  4. The messages I send group together, sometimes appearing above other messages, sometimes below

Here is an image of the issue:

enter image description here

Notice how some younger messages are above some older messages, and grouped by the user who sent it!

This is how I write the message to the DB:

onSend = async(message) => {
        this.setState({isTyping: true})
        await Firebase.firestore().collection("chat")
        .add({
            user: {
                _id: this.state.currentUser.id,
                name: this.state.currentUser.name,
                avatar: this.state.currentUser.avatar,
            },
            
        })
        .then(ref => this.setState({messageID: ref.id}))

        await Firebase.firestore().collection("chat")
        .doc(this.state.messageID)
        .set({
            _id: this.state.messageID,
            text: message[0].text,
            createdAt: dayjs(Moment(message[0].createdAt).format('LLL')).locale('en-ca').format()
        }, { merge: true })

    }

    render() { 
        return (
            <View style={{backgroundColor: '#000000', flex: 1}}>
                <GiftedChat
                    showUserAvatar={true}
                    isTyping={this.state.isTyping}
                    renderUsernameOnMessage={true}
                    messages={this.state.messages}
                    onSend={message => this.onSend(message)}
                    scrollToBottom
                    locale = { dayjs.locale('en-ca') }
                    showAvatarForEveryMessage = {true}
                    dateFormat = 'll'
                    timeFormat = 'LT'
                    onPressAvatar={user => this.getProfile(user)}
                />
            </View>
            
        )
        
    }
}

How I read the messages:

getCurrentMessages = async() => {

        await Firebase.firestore().collection("chat")
        .orderBy("createdAt", "desc")
        .limit(50)
        .onSnapshot(querySnapshot => {
            const messages = []

            querySnapshot.forEach((res) => {
                const { 
                    _id,
                    user,
                    text,
                    createdAt,
                    } = res.data();
    
                    messages.push({
                        key: res._id,
                        _id,
                        user,
                        text,
                        createdAt,
                    });
            })

            this.setState({
                messages,
                isLoading: false, 
                isTyping: false
            });
        })
    }

In firestore, this is how the time is written to the db:

enter image description here

Any idea why the messages are getting grouped together?

It seems like a simple case of pulling the messages from firestore ordered by date created, but that doesn't look like its working correctly.

I also get the following error when I send a message in gifted chat, could this have something to do with it?

react-native-gifted-chat] GiftedChat: `user` is missing for message {"_id":"lxYBMTV0sD7kaLQOsQLp","text":"Test 5","createdAt":"2021-01-25T22:05:00-08:00"}

[Some of the messages were sent from the east coast, some from the west coast of the USA. I wonder if this has something to do with the groupings?]


Solution

  • As per the image it seems, the createdAt field is not a timestamp field, it's a String.

    To add a timestamp field as mentioned here

    createdAt: new Date();
    
    or specific date-time
    
    createdAt: firestore.Timestamp.fromDate(new Date());
    
    or else for server time
    
    createdAt: firestore.FieldValue.serverTimestamp()
    

    enter image description here

    If you are able to get the field corrected, your orderBy query would retrieve the data in correct order.

    Now the ordering happens on a String field, so it won't work as expected!