如何防止 React 中的多个套接字连接和事件

2025-06-08

如何防止 React 中的多个套接字连接和事件

在 SPA 中,多个套接字连接和事件绑定很容易被忽视,并可能导致问题。我想分享一些避免这些问题的经验。在本文中,我将分别socket.io针对 Node.js 后端和socket.io-clientReact 前端进行讲解。

1. 仅连接一次

为套接字连接创建专用文件。例如,在以下位置创建一个文件service/socket.js




import io from "socket.io-client";
import { SOCKET_URL } from "config";

export const socket = io(SOCKET_URL);


Enter fullscreen mode Exit fullscreen mode

您可以在必要时在其他 React 组件中导入此套接字实例:



import {socket} from "service/socket";

function MyComponent() => {
   return(<div></div>)
}


Enter fullscreen mode Exit fullscreen mode

这样,就可以确保只有一个套接字实例。

2. 仅绑定和发出一次事件 - 将它们放在正确的位置

假设你正在构建一个 React 组件,该组件在页面加载时连接到套接字服务器,并在连接成功时显示欢迎消息。该组件将向HELLO_THERE服务器发出一个事件,服务器将响应一个 warmWELCOME_FROM_SERVER事件。你应该在 React 代码的哪个位置绑定和触发套接字事件?



import {socket} from "service/socket";
// NOT HERE (1)
// socket.emit('HELLO_THERE');
function MyComponent() => {

   // NOT HERE EITHER (2)
   // socket.emit('HELLO_THERE');
   const [connected, setConnected] = useState(false);
   // IT IS HERE
   useEffect(() => {
      socket.emit('HELLO_THERE');
      const eventHandler = () => setConnected(true);
      socket.on('WELCOME_FROM_SERVER', eventHandler);
      // unsubscribe from event for preventing memory leaks
      return () => {
         socket.off('WELCOME_FROM_SERVER', eventHandler);
      };
   }, []);
   return (
      <div>
          { connected ? (
               <p>Welcome from server!</p>
          ) : (
               <p>Not connected yet...</p>
          ) }
      </div>
   )
}
export default MyComponent


Enter fullscreen mode Exit fullscreen mode
  • MyComponent(1)即使未使用,也会发出事件。
  • MyComponent(2)每当更新时都会发出事件。

* 如果你正在使用 React 类,componentDidMount那么这里就是使用套接字的正确位置。useEffect(() => {}, [])几乎与**相同componentDidMount
,当然,socket.emit它可以放在代码中任何需要的地方。但是,在大多数情况下,socket.on应该在。componentDidMount

3. 如果你不确定,总有这个技巧

如果您仍然无法弄清楚为什么您的组件愚蠢地多次绑定同一个监听器,或者您只是想确保为一个事件只绑定一个监听器,您可以求助于socket.off



socket.off('MY_EVENT', doThisOnlyOnce).on('MY_EVENT', doThisOnlyOnce);


Enter fullscreen mode Exit fullscreen mode

更新 - useContext 方法

如果你想使用useContext钩子,你可以这样做:

socket.js



import React from "react";
import io from "socket.io-client";
import { SOCKET_URL } from "config";

export const socket = io(SOCKET_URL);
const SocketContext = React.createContext(socket);


Enter fullscreen mode Exit fullscreen mode

您的app.js内容应该如下所示:



import React from "react";
import SocketContext, { socket } from "context/socket";

const App = () => (
   <SocketContext.Provider value={socket}>
      <OtherComponents />
   </SocketContext.Provider>
);


Enter fullscreen mode Exit fullscreen mode

然后,在组件的任何地方,您都可以像这样获取套接字:



import React from "react";
import SocketContext from "context/socket";

const OtherComponent = () => {
  const socket = React.useContext(SocketContext);
  ...
};


Enter fullscreen mode Exit fullscreen mode

欲了解更多信息,您可以阅读我的另一篇文章:

鏂囩珷鏉ユ簮锛�https://dev.to/bravemaster619/how-to-prevent-multiple-socket-connections-and-events-in-react-531d
PREV
在 React 应用中嵌入 Youtube 视频的最简单方法
NEXT
升级到 Angular v12 后开发服务速度加快