0

I have this code :

useEffect(() => {
    const init = async () => {
      try {
        socketRef.current = await initSocket();

        socketRef.current.on("connect_error", (err) => handleErrors(err));
        socketRef.current.on("connect_failed", (err) => handleErrors(err));

        function handleErrors(e) {
          console.log("socket error", e);
          toast.error("Socket connection failed, try again later.");
          navigate("/dashboard");
        }
        function DisconnectRoom({ socketId, username }) {
          toast.info(`${username} left the room`);
          setClients((prev) => {
            return prev.filter((client) => client.socketId !== socketId);
          });
        }
        function JoinedRoom({ clients, userName, socketId }) {
          if (username !== userName) {
            toast.success(`${userName} joined the room!`);
            socketRef.current.emit(Actions.SYNC_CODE, {
              roomId,
              code: codeRef.current,
              socketId,
              name: "all",
            });
          }
          setClients(clients);
        }
        socketRef.current.emit(Actions.JOIN, {
          roomId,
          username,
        });

        socketRef.current.on(Actions.JOINED, JoinedRoom);

        socketRef.current.on(Actions.DISCONNECTED, DisconnectRoom);
      } catch (e) {
        console.log(e);
      }
    };
    init();

    return () => {
      socketRef.current.disconnect();
      socketRef.current.off(Actions.DISCONNECTED);
      socketRef.current.off(Actions.JOINED);
    };
  }, []);

The problem is when the cleanup function executes it gives an error that socketRef.current is null. I have already tried to put a condition -

if(socketRef.current) {
    socketRef.current.disconnect();
    socketRef.current.off(Actions.DISCONNECTED);
    socketRef.current.off(Actions.JOINED);
}

But now it connects a client two times probably because in strictmode react call a function 2 times. Could anyone please help me to fix this

I tried to connect one client to socket but as mentioned above if I check socketRef.current then it connects a client two times and if I don't the it gives error that socketRef.current is null.

1 Answer 1

0

Is it a requirement to use a ref for the socket connection? Why don’t you use a variable inside the useEffects scope to keep track of your socket instance?

Pseudo-code:


let socket;
socket = createConnection();
return () => {
  if (socket) {
    socket.disconnect();
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I am using a ref beacuse it's value persist across renders and I don't want to create a socket connection everytime an new render occurs. I am making a realtime codeEditor so the state which stores the code changes everytime you write something.
The solution I propose does not recreate the socket on every render, but only when useEffect runs.
Thanks egge I used wrote initSocket function inside a useCallback and it worked

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.