首页 > 解决方案 > 如何避免与 socket.io-client 和 React 应用程序重新连接?

问题描述

我试图将 React 客户端连接到我的 Socket.IO 服务器。我注意到 Socket.IO 客户端每 +/- 5 秒重新连接一次。当我尝试使用 vanilla html/js 简单应用程序做同样的事情时,一切正常。

React 组件内部:

useEffect(() => {
  const s = getChatClient();
}, []);

在 socket.io-client 模块内部:

var chatClient;

export function getChatClient(
  token = "secret"
) {
  if (!chatClient) {
    chatClient = io("http://localhost:5000/chat", {
      query: {
        token,
      },
    });
    chatClient
      .on("connect", () => {
        chatClient.emit("textMessage", "123cos");
      })
      .on("hello", (msg) => {
        console.log("12");
      });
  }
  return chatClient;
}

顺便说一句:我知道我可以导出 const 等(我已经更改为这个版本,因为我认为它会有所帮助)。

我尝试了不同的方法来解决这个问题,但我陷入了困境。有任何想法吗?

当我打开 html/js 简单客户端时从服务器登录:

15:30:00 User Ilona connected to the socket.io server on /

当我退出时:

  15:29:12 User Ilona disconnected 

使用 React 应用程序:

  15:30:00 User Ilona connected to the socket.io server on '/'
  15:30:05 User Ilona disconnected 
  15:30:10 User Ilona connected to the socket.io server on '/' 
  15:30:15 User Ilona disconnected 
  15:30:20 User Ilona connected to the socket.io server on '/' 
  15:30:25 User Ilona disconnected

该问题与组件重新渲染或类似问题无关。

我正在开发 MacOS Big Sur。

标签: reactjssocket.io

解决方案


考虑创建,然后从上下文中使用:

SocketContext.jsx:

import { createContext, useState } from 'react';

export const SocketContext = createContext();

export default function SocketContextProvider(props) {
  const [sock, setSocket] = useState(null);

  let socket = async () => {
    if (sock) {
      return Promise.resolve(sock); // If already exists resolve
    }
    return new Promise((resolve, reject) => {
      let newSock = io('URL'),
        {
          query: {
            // Options
          },
        }; // Try to connect
      
      let didntConnectTimeout = setTimeout(() => {
        reject();
      }, 15000) // Reject if didn't connect within 15 seconds

      newSock.once('connect', () => {
        clearTimeout(didntConnectTimeout); // It's connected so we don't need to keep waiting 15 seconds
        setSocket(newSock); // Set the socket
        resolve(newSock); // Return the socket
      })
    });
  };

  return (
    <SocketContext.Provider value={{ socket }}>
      {props.children}
    </SocketContext.Provider>
  );
}

组件.jsx:

import { useContext, useState, useEffect } from 'react';
import { SocketContext } from './SocketContext.jsx';

export default function MyComponent() {
  const { socket } = useContext(SocketContext);
  const [sock, setSock] = useState(null);

  useEffect(() => {
    socket()
      .then((resultSocket) => setSock(resultSocket))
      .catch(() => {
      /* Catch any errors here */
        console.log('Couldn\'t connect the socket!')
      });
  }, []);

  return (
    <div>
      <code>I'm a context consumer...</code>
    </div>
  );
}

推荐阅读