javascriptreactjschatmessengerreact-fullstack

How do I get messages to appear right away? It works for new conversations (first block), but not for the existing conversations (second block)


The below code works for addNewConvo (new conversations), but not for addMessagetoConversation (existing conversations). I thought I did the same process for both, but I am missing something in the second part.

  const addNewConvo = useCallback(
    (recipientId, message) => {
      const newConversations = conversations.map((convo) => {
        if (convo.otherUser.id === recipientId) {
          //  convo.messages.push(message);
          //  convo.latestMessageText = message.text;
          //  convo.id = message.conversationId;
          return {
            ...convo,
            messages: [...convo.messages, message],
            latestMessageText: message.text,
            id: message.conversationId
          }
        }
        return convo
      });
      setConversations(newConversations);
    },
    [setConversations, conversations]
  );

  const addMessageToConversation = useCallback(
    (data) => {
      // if sender isn't null, that means the message needs to be put in a brand new convo
      const { message, sender = null } = data;
      if (sender !== null) {
        const newConvo = {
          id: message.conversationId,
          otherUser: sender,
          messages: [message],
        };
        newConvo.latestMessageText = message.text;
        setConversations((prev) => [newConvo, ...prev]);
      }

      conversations.forEach((convo) => {
        if (convo.id === message.conversationId) {
          //  convo.messages.push(message);
          //  convo.latestMessageText = message.text;
          return {
            ...convo,
            messages: [...convo.messages, message],
            latestMessageText: message.text,
          }
        }
        return convo
      });
      setConversations(conversations);
    },    
    [setConversations, conversations]
  );

Solution

  • forEach executes a callback for every element in an array but doesn't mutate the array or return anything. In your case you do want to mutate it, so what you would do is map through the conversations and update the conversation if the id matches. You would also need to assign the results of the map to a new variable since it doesn't mutate the original array.

    const newConversations = conversations.map((convo) => {
            if (convo.id === message.conversationId) {
              //  convo.messages.push(message);
              //  convo.latestMessageText = message.text;
              return {
                ...convo,
                messages: [...convo.messages, message],
                latestMessageText: message.text,
              }
            }
            return convo
          });
       setConversations(newConversations);