Warm tip: This article is reproduced from serverfault.com, please click

How to execute a sort after loading in data into an array in UseEffect

发布于 2020-11-19 21:57:39

I'm trying to create a chat app and there is a small issue. Whenever I load in my messages from firebase, they appear in the chat app in unsorted order, so I'm attempting to sort the messages by timestamp so they appear in order. I can do this if I move the sort and setMessages within onReceive of useEffect, but I feel like this will be pretty inefficient because it sorts and setsMessages a separate time for each message that's retrieved from firebase. I want to just do it all at the end after all the messages are loaded into the array.

Right now with my logs, I get this:

[REDACTED TIME]  LOG      []
[REDACTED TIME]  LOG      pushing into loadedMessages
[REDACTED TIME]  LOG      pushing into loadedMessages

So it's printing the (empty) array first, then loading in messages. How can I make sure this is done in the correct order?

  useEffect(() => {
    // Gets User ID
    fetchUserId(getUserId());

    const messagesRef = firebase.database().ref(`${companySymbol}Messages`);
    messagesRef.off();

    messagesRef.off();
    const onReceive = async (data) => {
      const message = data.val();
      const iMessage = {
        _id: message._id,
        text: message.text,
        createdAt: new Date(message.createdAt),
        user: {
          _id: message.user._id,
          name: message.user.name,
        },
      };
      loadedMessages.push(iMessage);
      console.log('pushing into loadedMessages');
    };
    messagesRef.on('child_added', onReceive);

    loadedMessages.sort(
      (message1, message2) => message2.createdAt - message1.createdAt,
    );

    console.log(loadedMessages);

    return () => {
      console.log('useEffect Return:');
      messagesRef.off();
    };
  }, []);
Questioner
Andrew
Viewed
0
Shahar 2020-11-28 14:13:29

I think that the perspective is a bit off. The right way to do so will be to fetch the firebase data sorted.

Firebase has a built-in sort, although it does come with its limitations.

In my opinion, you sould try something like:

const messagesRef = firebase.database().ref(`${companySymbol}Messages`);

messagesRef.orderByChild("createdAt").on("child_added", function(snapshot) {
  // the callback function once a new message has been created. 
  console.log(snapshot.val()); 
});

And if I may add one more thing, to bring every single message from the down of time can be a bit harry once you've got over a thousand or so, so I would recommend limiting it. that can be achieved using the built-in limit function limitToLast(1000) for example.

Good luck!