Search code examples
reactjs.netsignalr

Remove subscribed handler from a method when using signalR in react


I have signalR chat hub on the ASP.NET Core API, and I use @microsoft/signalr package in react, to connect websocket and invoke functions on the server. I have few handlers that handle messages sent from server. One of them is this:

  useEffect(() => {
    if (!connection) return

    connection.on("ReceiveMessage", (user, message) => {
      if (
        (message.fromUserId === authUserId &&
          message.toUserId === chattingUser?.id) ||
        (message.fromUserId === chattingUser?.id &&
          message.toUserId === authUserId)
      ) {
        const newMessages = [...chattingUser.messages]
        newMessages.push(message)
        setChattingUser((prevUser) => {
          return { ...prevUser, messages: newMessages }
        })
      }
    })
  }, [authUserId, chattingUser, connection])

This handler needs to change whenever something from dependencies is changed. When this useEffect runs, a new handler is created and handler(s) that are created before are NOT removed. This makes a lot of subscriptions to the same event, and when ReceiveMessage happens, all of previous handlers are executed. I couldn't find a solution to unsubscribe (remove) all previous handlers using @microsoft/signalr npm package.


Solution

  • Try:

    useEffect(() => {
        if (!connection) return
    
        // I added this line.
        connection.off("ReceiveMessage");
    
    
        connection.on("ReceiveMessage", (user, message) => {
          if (
            (message.fromUserId === authUserId &&
              message.toUserId === chattingUser?.id) ||
            (message.fromUserId === chattingUser?.id &&
              message.toUserId === authUserId)
          ) {
            const newMessages = [...chattingUser.messages]
            newMessages.push(message)
            setChattingUser((prevUser) => {
              return { ...prevUser, messages: newMessages }
            })
          }
        })
      }, [authUserId, chattingUser, connection])
    

    Basically, the point is, that there should be an off method, which can be used to unsubscribe.