YO Y
YO Y

Reputation: 131

realtime database listener makes CPU skyrocketing

i'm implementing chatting feature with realtime database of Firebase and React, and i wrote like this:

  useEffect(() => {
    messagesListeners(pid)
  }, [])

  const messagesListeners = async (pid: string) => {
    const messages = [];

    realtimeService
      .ref(`messages/post-${pid}`)
      .on('child_added', DataSnapshot => {
        messages.push(DataSnapshot.val())
        setComments([...messages])
      })
  }

but it's making browser's CPU skyrocketing. i think it's because of the part of "setComments". when i removed that part (setComments), this issue doesn't happen. if there are 100 of comments, that set comments 100 times.

How can i bring new comments without CPU's skyrocketing?

Upvotes: 0

Views: 59

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

The problem is in here::

setComments([...messages])

This call, adds your entire messages array to the end of the existing comments array. This leads to an exponentially growing comments array:

child_added messages comments
one [one] [one]
two [one,two] [one,one,two]
three [one,two,three] [one,one,two,one,two,three]
four [one,two,three,four] [one,one,two,one,two,three,one,two,three,four]
five [one,two,three,four,five] [one,one,two,one,two,three,one,two,three,four,one,two,three,four,five]
...

So the minimal fix is to set the comments array to the messages, instead of constantly appending:

setComments(messages)

You can also reduce the number of calls to setComments by listening to a value event, instead of child_added. The value event will fire only once for all comments, which you can then process with:

const messagesListeners = async (pid: string) => {
  realtimeService
    .ref(`messages/post-${pid}`)
    .on('value', snapshot => {
      const messages = [];
      snapshot.forEach((child) => {
        messages.push(child.val())
      });
      setComments(messages)
    })
}

Upvotes: 1

Related Questions