How can we close websockets connection when component unmount?

29 Views Asked by At

I am having a small bug in my application which causing a big problem. In my react-vite application, I have integrated WebSocket to get the live status of a particular thing.

Problem: When a user views the component, it should send the active status to the server. When the user leaves the page, the component should send inactive only. But in my current implementation, it sends the active status first, then when I leave it sends inactive and then active. I tried to send active and inactive only. But it doesn't work. As soon as it sends the "inactive" status, it sends the active afterward.

Why I am not closing the WebSocket? I tried to close it. But the method is not accepted for now from the react-use-websocket package.

What I am looking for? I am looking for only sending the active status when the component mounts and inactive when the component unmounts.

I am looking for a solid solution or suggestion from you guys. Anything from your end would be appreciated. Open to learn anything. Thanks in advance.

The package I have used here for WebSocket: react-use-websocket

Code:

Server Url:

const socketUrl = `wss://my-web-server/v1/api/wall/set/user/status/${token}/${id}`;

Here's how I use it:

  const { sendJsonMessage, readyState, } = useWebSocket(socketUrl, { share: true });

Sending the message:

  //common function for sending message
  const sendJsonMessageToServer = useCallback((status: any) => {
  if (readyState === WebSocket.OPEN) {
    sendJsonMessage(status);
  }
},
[readyState, sendJsonMessage]);

 //useEffect for checking if the component get mounted or not. 
  useEffect(() => {
sendJsonMessageToServer({ status: "active" });
return () => {
  if (readyState === ReadyState.OPEN) {
    sendJsonMessageToServer({ status: "inactive" });
  }
}; }, [readyState, sendJsonMessageToServer]);
1

There are 1 best solutions below

3
Harshal On

import React, { useEffect } from 'react';

const YourComponent = ({ token, id }) => {
  useEffect(() => {
    const socketUrl = `wss://my-web-server/v1/api/wall/set/user/status/${token}/${id}`;
    const socket = new WebSocket(socketUrl);

    socket.onopen = () => {
      socket.send(JSON.stringify({ status: 'active' }));
    };

    return () => {
      socket.send(JSON.stringify({ status: 'inactive' }));
      socket.close();
    };
  }, [token, id]);

  return <div>Your component content</div>;
};

export default YourComponent;

The problem you're facing might be due to the asynchronous nature of WebSocket connections and the timing of component unmounting in React.

Try this:-

import React, { useEffect } from 'react';
import { useWebSocket, ReadyState } from 'react-use-websocket';

const YourComponent = ({ token, id }) => {
  const socketUrl = `wss://my-web-server/v1/api/wall/set/user/status/${token}/${id}`;
  const { sendJsonMessage, readyState } = useWebSocket(socketUrl, { share: true });

  useEffect(() => {
    if (readyState === ReadyState.OPEN) {
      sendJsonMessage({ status: 'active' });
    }

    return () => {
      if (readyState === ReadyState.OPEN) {
        sendJsonMessage({ status: 'inactive' });
      }
    };
  }, [sendJsonMessage, readyState]);

  return <div>Your component content</div>;
};

export default YourComponent;