如何在 React 中正确的使用 socket.io 客户端?

更新日期: 2022-06-13阅读: 806标签: socket

最近在一个 react 项目中,使用到了 socket.io 处理即时消息,这里面有几点容易被忽视的问题,例如:在 React 单页面应用中如何防止出现多个 socket 实例、在任意的的组件内如何方便的取到 socket 实例、对于某个事件不要随着页面切换出现多个监听器。

在本文中,将会给大家分享下我在 React 中使用 Socket.io 客户端的一些经验,希望对此有疑惑的朋友给予一些帮助,也许你会有一些更好的实现方式,欢迎交流!

创建 Socket Context

本文的实现方式是使用状态管理工具保存 socket 实例,供子组件使用,如果使用了 React Hooks,可以用其提供的 useContext api,实现起来也很简单。

// contexts/socket.tsx
import { createContext, ReactNode, useContext } from 'react';
import io, { Socket } from 'socket.io-client';

const SOCKET_URL = 'ws://localhost:8080';
export const socket = io(SOCKET_URL, {
  transports: ['websocket'],
});

const SocketContext = createContext<Socket>(socket);
SocketContext.displayName = 'SocketContext';

export const SocketProvider = ({ children }: { children: ReactNode }) => (
  <SocketContext.Provider value={socket}>{children}</SocketContext.Provider>
);

export const useSocket = () => {
  const context = useContext(SocketContext);
  return context;
};

// contexts/index.tsx
import { ReactNode } from 'react';
import { SocketProvider } from './Socket';

const AppContextProviders = ({ children }: { children: ReactNode }) => (
  <SocketProvider>{children}</SocketProvider>
);

export default AppContextProviders;

其中  const socket = io(SOCKET_URL),有些朋友可能就有疑问了,为什么不执行下 socket.connect() 呢?

socket.io 客户端默认是自动链接的,如果声明了 autoConnect 属性为 false,则需要手动执行下链接。

以上,在页面第一次加载时会初始化 socket,解决了第一个问题:“React 单页面应用中如何防止出现多个 socket 实例”。

根组件提供 socket

在项目的 App.js 文件中引入我们自定义的 Providers,将 AppProviders 组件做为根组件放在最顶层,这样被包裹的组件都可以使用 AppProviders 组件提供的属性。也解决了第二个问题:“在任意的的组件内如何方便的取到 socket 实例”。

import AppProviders from './contexts';
import './App.css';

const App = () => (
  <AppProviders>
    ...
  </AppProviders>
);

export default App;

任意子组件中使用 socket

组件 A,监听服务器发来的消息。

useEffect() 是 React 内置的一个 Hook,如果第二个参数依赖项数组为空,那么传入的第一个函数在该组件内只会执行一次,依赖项数组只要有一个状态被更新,useEffect() 传入的第一个函数也将会被执行。

还需要注意的是 useEffect() 传入的第一个函数,它又返回的函数在函数组件卸载时被调用,通常我们会用 useEffect() 模拟类组件的 componentDidMount、componentWillUnmount 行为。

在组件卸载时,使用 socket.off() 移除事件监听器,实际上这可以预防内存泄漏,同时也解决了最开始提的第三个问题:“对于某个事件不要随着页面切换出现多个监听器”。

import { useEffect } from 'react';
import { useSocket } from '../../contexts/Socket';

const ComponentA = () => {
  const socket = useSocket();

  useEffect(() => {
    // componentDidMount
    socket.on('message', handleMessage); // 监听消息
    return () => {
      // componentWillUnmount
      socket.off('message', handleMessage);
    };
  }, [socket]);
  
  return ();
};
    
export default ComponentA;

组件 B,发送消息到服务器。

在我们的组件 B 中,也可以使用自定义的 useSocket Hook 获取最开始初始化的 socket 实例,但这并不会产生一个新的 socket 实例。

import { useEffect } from 'react';
import { useSocket } from '../../contexts/Socket';

const ComponentB = () => {
  const socket = useSocket(); 
  const handleSendMessage = () => {
    socket.emit('compress', data); // 发送消息
  }
  
  return <div>
    // ...
    <button onClick={handleSendMessage}>Send message</button>
  </div>;
};
    
export default ComponentB;

来源: 编程界

链接: https://www.fly63.com/article/detial/11714

web Socket和Socket.IO框架

HTTP无法轻松实现实时应用:HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。我们可以非常轻松的捕获浏览器上发生的事件(比如用户点击了盒子)

Nginx 转发 socket 端口配置

Nginx 转发 socket 端口常见场景:在线学习应用,在常规功能之外,增加一个聊天室功能,后端选择 swoole 提供服务提供者,同时不想前端直接 ip:port 方式链接到服务,需要使用 Nginx 进行转发。

websocket.io

服务器端:使用express服务;简单的使用websocket.io;使用命名空间 实例中两个命名空间info job;客户端 vue为例引入socket.io-client

Socket通信原理.一文了解Socket

Socket 的中文翻译过来就是“套接字”。套接字是什么,我们先来看看它的英文含义:插座。Socket 就像一个电话插座,负责连通两端的电话,进行点对点通信,让电话可以进行通信,端口就像插座上的孔,端口不能同时被其他进程占用。而我们建立连接就像把插头插在这个插座上

Vue.js 如何使用 Socket.IO

Socket.IO是一个WebSocket库,可以在浏览器和服务器之间实现实时,双向和基于事件的通信。它包括:Node.js服务器库、浏览器的Javascript客户端库。它会自动根据浏览器从WebSocket、AJAX长轮询、

轮询、长轮询、长连接、socket连接、WebSocket

轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接;长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接

封装小程序的websocket

这两天的工作中,我重构了一个项目里的客服聊天功能,是小程序的,用了小程序提供的websocket有关的接口,我感觉很简单,和web端的接口大体一致,不过我喜欢封装后去使用,封装成一个类,创建一个类的实例

使用Promise封装Websocket

await 后面若是跟的Promise,则接受Promise resolve的值。Promise reject的值需要try...catch住,或者await 后面的表达式跟着.catch()

socket.io的接入使用

传统的客户端和服务器通信协议是HTTP:客户端发起请求,服务端进行响应,服务端从不主动勾搭客户端。这种模式有个明显软肋,就是同步状态。而实际应用中有大量需要客户端和服务器实时同步状态的场景

Web 全栈推拉能手 Socket.IO 库

Socket.IO 不仅支持 WebSocket,还支持许多种轮询机制以及其他实时通信方式,并封装了通用的接口。这些方式包含 Adobe Flash Socket、Ajax 长轮询、Ajax multipart streaming 、持久 Iframe、JSONP 轮询等

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!