WebbH
WebbH

Reputation: 2422

React and Firebase: adding date to database causes listener to trigger twice?

I have a very simple chat app. Upon submit, it updates the database with the username and the message.

this.ref.child("/chat").update({username: this.state.username, 
    message: this.state.chatMessage});

I then use a ref.on('value',()) to get the new chat and store it in an array.

this.chat.on('value',(snapshot) => {
    console.log('triggered')
    let newMessage = {username:snapshot.val().username, message: snapshot.val().message}
    this.setState({chatArray: [...this.state.chatArray,newMessage]})
}) 

I was trying to think of a workaround to getting duplicate messages (i.e. typing the same message again, since the listener is not triggered if nothing changes) so I though I'd add a date object to the database. When I added the date to the database using

let d = new Date();
this.ref.child("/chat").update({username: this.state.username, 
    message: this.state.chatMessage, time: d});

The event listener started being triggered twice when I wrote something and submitted it. The user that submitted the chat would get the same message twice and the other user would get it just once. Removing the date fixed the issue.

Does anyone know why this would happen?

Upvotes: 0

Views: 1248

Answers (3)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

The Firebase Database stored JSON, and Date isn't a valid JSON type. The idiomatic approach is to store a timestamp:

this.ref.child("/chat").update({username: this.state.username, 
    message: this.state.chatMessage, time: Date.now()});

Upvotes: 1

Benjamin Scholtz
Benjamin Scholtz

Reputation: 823

The reason the on(value, () => {}) listener is triggered twice is that it operates by first fetching and returning the current value, and is then triggered for every subsequent database entry change - if all you want to do is fetch the current value, then you can use the method as described by @Peter Haddad .

Something that is useful to note, is that Firebase guarrantees the following, as seen in their documentation:

Value events are always triggered last and are guaranteed to contain updates from any other events which occurred before that snapshot was taken.

This means that if you call once(value, () => {}) after your call to update the database entry, you are guarranteed that the update has occured and the data returned in the listener includes the updates.

Upvotes: 0

Peter Haddad
Peter Haddad

Reputation: 80914

Change this:

this.chat.on('value',(snapshot) => {

into this:

this.chat.once('value').then((snapshot)=> {

This is way it will only b triggered once, more info here:

https://firebase.google.com/docs/database/web/read-and-write#read_data_once

Upvotes: 0

Related Questions