如何防止 React 中的多个套接字连接和事件
在 SPA 中,多个套接字连接和事件绑定很容易被忽视,并可能导致问题。我想分享一些避免这些问题的经验。在本文中,我将分别socket.io
针对 Node.js 后端和socket.io-client
React 前端进行讲解。
1. 仅连接一次
为套接字连接创建专用文件。例如,在以下位置创建一个文件service/socket.js
:
import io from "socket.io-client";
import { SOCKET_URL } from "config";
export const socket = io(SOCKET_URL);
您可以在必要时在其他 React 组件中导入此套接字实例:
import {socket} from "service/socket";
function MyComponent() => {
return(<div></div>)
}
这样,就可以确保只有一个套接字实例。
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
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);
更新 - 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);
您的app.js
内容应该如下所示:
import React from "react";
import SocketContext, { socket } from "context/socket";
const App = () => (
<SocketContext.Provider value={socket}>
<OtherComponents />
</SocketContext.Provider>
);
然后,在组件的任何地方,您都可以像这样获取套接字:
import React from "react";
import SocketContext from "context/socket";
const OtherComponent = () => {
const socket = React.useContext(SocketContext);
...
};
欲了解更多信息,您可以阅读我的另一篇文章:
鏂囩珷鏉ユ簮锛�https://dev.to/bravemaster619/how-to-prevent-multiple-socket-connections-and-events-in-react-531d