Aashiq Otp
Aashiq Otp

Reputation: 85

Only last data is fetched from firesbase after refreshing the page with firebase .on()

I am experiencing a strange problem with firebase Realtime DB.problem is with a chat component.

 componentDidMount(){
  this.renderMessages();
 }

renderMessages(){
rdb.ref("chats/"+this.props.id).orderByChild("time").on('child_added',   (snapshot)=>{
             if(snapshot.exists)
            {
                this.setState({messages [...this.state.messages,snapshot.val()]})
            }

    })
}

then map through this state and pass data to other components and everything works fine on the first run.

consoled Object On the first run [ it is an array of objects ]

   0: Object { message: "hello", read: false, sender: "Shan", … 
   1: Object { message: "Hai Shan", read: false, sender: "AashiqOtp", … }
   2: Object { message: "hi", read: false, sender: "AashiqOtp", … }  

when I go back and re-entered into the component it then it only shows the last object of the array ie

0: Object { message: "hi", read: false, sender: "AashiqOtp", … }

what's the issue? can someone help me out? Thanks in advance.

UPDATED

I am using " .once " event listener there are no problems, but as it is a chat component I need to always listen to the event.

Upvotes: 0

Views: 131

Answers (1)

Adam Jeliński
Adam Jeliński

Reputation: 1788

This is issue related to state not updating fast enough. You should use an updater function, if your new state is based on the old one.

Also, you shouldn't call this.setState multiple times in the forEach and instead add the whole array at once, to avoid many unnecessary rerenders and issues like this one

renderMessages(){
    rdb.ref("chats/"+this.props.id).on('value', (snapshot) => {
        this.setState(prevState => ({
            messages: [
                ...prevState.messages, 
                ...snapshot
                    .filter((childsnap) => childsnap.exists)
                    .map((childsnap) => childsnap.val())
            ]
        }))
    })
}

Since you changed the event in the question, there is no way to add the whole array at once and you have to use the less efficient method:

renderMessages(){
    rdb.ref("chats/"+this.props.id).orderByChild("time").on('child_added', (snapshot) => {
        if (snapshot.exists) {
            this.setState(prevState => ({
                messages: [
                    ...prevState.messages, 
                    snapshot.val()
                ]
            }))
        }
    })
}

Upvotes: 1

Related Questions