skip to Main Content

I just updated to React 18 and I noticed that the useEffect runs twice which makes my socket io code fail connection. What could be the solution for this?

Here is my useEffect:

  useEffect(() => {
    dispatch(connect());
    return () => dispatch(disconnect());
  }, []);

This is supposed to run on mount so just once but with the new changes in React 18, it does not. I get the following error:

WebSocket connection to 'ws://localhost:4444/socket.io/?EIO=4&transport=websocket&sid=tvz2_YPur_k2czFbAAAo' failed: WebSocket is closed before the connection is established.

When I remove the StrictMode, it works fine as usual so the problem comes from the new useEffect change in react 18.

EDIT:
So I played with it more and I noticed that if I remove the return () => dispatch(disconnect()) from the cleanup, it works fine.

Why would that be?

Like this:

      useEffect(() => {
        dispatch(connect());
      }, []);

2

Answers


  1. In your case, you can add an empty dependency array to ensure that the effect only runs once when the component mounts:

    Notice: Remove <React.StrictMode> from the first component and let’s
    see fix twice run or not.

    try this code to connect websocket:

    import { w3cwebsocket as W3CWebSocket } from 'websocket';
    
    const websocketURL = 'Your WebSocket Connection';
    
    const SampleWebSocket= () => {
           useEffect(() => {
             const websocket = new W3CWebSocket(websocketURL);
               
             websocket.onerror = (err) => console.warn('ERROR websocket', err);
    
             websocket.onmessage = (event) => {
              console.log(JSON.parse(event.data));
    
            *//it possible to set up an interval to send a ping to the server and keep the connection alive* 
                const pingInterval = setInterval(() => {
                    websocket.send(JSON.stringify({ title: 'Pong' }));
                }, 30000);
            }
    
    
            return () => {
    
                clearInterval(pingInterval);
                websocket.close();
    
            };
    
           },[]);
    }
    
    export default SampleWebSocket;
    

    Make sure websocket package has been installed npm i websocket --develop

    Login or Signup to reply.
  2. Unfortunately WebSockets are a stateful communication layer, and React tries to be a stateless library. React 18 strict mode always mounts and unmounts multiple times reveal statefulness.

    You could try https://www.npmjs.com/package/react-use-websocket, a library that has a global socket manager outside of React that gives you access to sockets.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search