0

I'm trying to update my messages array when I receive a message event from socket. However the code I have right now isn't being executed in the ChatMain component.

export const ChatMain = ({ selectedContact }) => {
const [isMessagesLoading, setIsMessagesLoading] = useState(true)
  const [messageRecieved, setMessageRecieved] = useState(false)

  const [dataMessageArray, setDataMessageArray] = useState([])
  const [messageSortedAccending, setMessageSortedAccending] = useState([])

  const [messageInputValue, setMessageInputValue] = useState("")

// this is the event that registers received messages 
 socketService.onMessage(function (message) {
    setMessageRecieved(true)
    console.log(messageRecieved)
    setDataMessageArray([
      ...dataMessageArray,
      {
        from: message.From,
        body: message.Body,
        to: message.To,
        sid: message.SmsSid,
        dateCreated: new Date(),
      },
    ])
  })

Socket services are being made from an external class

```
export class socketService {
static onMessage(callback) {
    socket.on("message-receive", callback)
  }
}
```

I have one useEffect to load all the messages the first time

// Get messages for selected contact and reload chat
  useEffect(() => {
    if (selectedContact) {
      setDataMessageArray([])
      setIsMessagesLoading(true)
      ApiService.getMessages(selectedContact)
        .then((data) => {
          setDataMessageArray(data.data)
          setIsMessagesLoading(false)
        })
        .catch((err) => console.log(err))
    }
  }, [selectedContact, messageRecieved])

and another useEffect that sorts the messages in the chat

 // Sort the messages in ascending order and reload chat
  useEffect(
    function () {
      setMessageInputValue("")
      const messageSortedAccending = dataMessageArray
        .sort((a, b) => {
          a = moment(new Date(a.dateCreated))
          b = moment(new Date(b.dateCreated))

          return b.diff(a)
        })
        .reverse()
      setMessageSortedAccending(messageSortedAccending)
    },
    [dataMessageArray]
  )

the messages are returned from the sorted messages array called messageSortedAccending.

like so :

...
 <MessageList>
        {isMessagesLoading
          ? new Array(6).fill(0).map((_, i) => <MessageLoader key={i} />)
          : messageSortedAccending.map((msg) => (
              <Message msg={msg} phoneNumber={phoneNumber} />
            ))}
      </MessageList>
...

How can I re-render the chat when a new message is received ? Currently I have to reload the page to check if a new message has arrived, but that is not correct. Am I doing something wrong here ?

Esam Olwan
  • 320
  • 1
  • 5
  • 16
  • Random first impression: why is your `socketService.onMessage( ... )` not in a `useEffect`? The way you have it, each render is installing a new `onMessage` handler. See [this approach](https://stackoverflow.com/a/55566585/1563833) – Wyck Oct 21 '22 at 13:31

0 Answers0