'Use Effect doesn't run on websocket ON

I am working on a websocket project in react. But when I send a message, the websocket does reload to display new messages. I have to reload my page manually to show the changes.

Here's my use Effect Hook

useEffect(() => {
    if (socket.current) {
      socket.current.on('msgSent', ({ newMsg }) => {
        console.log('MESSAGE SENT', newMsg)
        if (newMsg.receiver === openChatId.current) {
          setMessages((prev) => [...prev, newMsg])

          setChats((prev) => {
            const previousChat = prev.find(
              (chat) => chat.messagesWith === newMsg.receiver
            )
            previousChat.lastMessage = newMsg.msg
            previousChat.date = newMsg.date

            return [...prev]
          })
        }
      })
    }
  }, [])

When I remove the useEffect dependency (i.e []), It works but it renders the message multiple times on the screen.

Here's the rest of my frontend client code

const openChatId = useRef('')

  const auth = useContext(AuthContext)
  const queryMessage = new URLSearchParams(search).get('message')

  useEffect(() => {
    if (!socket.current) {
      socket.current = io(process.env.REACT_APP_API)
    }

    if (socket.current) {
      socket.current.emit('join', { userId: auth.user._id })

      socket.current.on('connectedUsers', ({ users }) => {
        users.length > 0 && setConnectedUsers(users)
      })
    }

    if (chats.length > 0 && !queryMessage) {
      history.push(`/messages?message=${chats[0].messagesWith}`, undefined, {
        shallow: true,
      })
    }

    return () => {
      if (socket.current) {
        socket.current.emit('logout')
        socket.current.off()
      }
    }
  }, [chats])

  useEffect(() => {
    const getAllChats = async (token) => {
      try {
        setLoading(true)
        const res = await getChats(token)
        if (res) {
          setChats(res)
          setLoading(false)
        }
      } catch (err) {
        console.log(err)
        setLoading(false)
      }
    }

    getAllChats(auth.token)
  }, [])

  useEffect(() => {
    const loadMessages = () => {
      socket.current.emit('loadMessages', {
        userId: auth.user._id,
        messagesWith: queryMessage,
      })

      socket.current.on('messagesLoaded', async ({ chat }) => {
        setMessages(chat.messages)
        setBannerData({
          firstName: chat.messagesWith.firstName,
          lastName: chat.messagesWith.lastName,
          profilePicUrl: chat.messagesWith.profilePicUrl,
        })

        openChatId.current = chat.messagesWith._id
      })

      socket.current.on('noChatFound', async () => {
        const { firstName, lastName, profilePicUrl } = await ChatGetUserInfo(
          queryMessage,
          auth.token
        )

        setBannerData({ firstName, lastName, profilePicUrl })
        setMessages([])

        openChatId.current = queryMessage
      })
    }

    if (socket.current) {
      loadMessages()
    }
  }, [queryMessage])

  const sendMsg = (msg) => {
    if (socket.current) {
      socket.current.emit('sendNewMsg', {
        userId: auth.user._id,
        msgSendToUserId: openChatId.current,
        msg,
      })
    }
  }

  

The backend works very well. U think my problem is with the useEffect



Solution 1:[1]

I fixed it. I was missing the [chats] dependency

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 James