使用React18和WebSocket构建实时通信功能详解
作者:Evan不懂前端
1. 引言
WebSocket是一种在Web应用中实现双向通信的协议。它允许服务器主动向客户端推送数据,而不需要客户端发起请求。在现代的实时应用中,WebSocket经常用于实时数据传输、聊天功能、实时通知和多人协作等场景。在本篇博客中,我们将探索如何在React 18应用中使用WebSocket来实现实时通信。
2. 准备工作
在开始之前,我们需要安装React 18,并确定你已经掌握了React Hooks的基本知识。此外,我们还将使用WebSocket的npm包来实现WebSocket连接。你可以通过以下命令使用npm或yarn来安装它:
npm install websocket # 或 yarn add websocket
3. 编写自定义钩子
import { useEffect, useRef, useState } from 'react'; import WebSocketClient from 'websocket'; export function useWebSocket(accessToken: string, requestName: string): SocketType { const clientRef = useRef<WebSocketClient | null>(null); const [isActive, setIsActive] = useState<boolean>(false); const [socketClient, setSockClient] = useState<WebSocketClient | null>(null); // 获取url let port = window.location.port; let wsUrl = ''; if (window.location.protocol === 'https:') { //如果当前是HTTPS加密的,那么使用wss if (!port) { port = '4174'; } wsUrl = 'wss:'; } else { if (!port) { port = '8080'; } wsUrl = 'ws:'; } wsUrl += `//${window.location.hostname}:${port}/api/ws/plugins/${requestName}?token=` + accessToken; if (!socketClient) { setSockClient(new WebSocketClient(wsUrl, isActive)); // 创建 WebSocketClient 实例并传入 URL 和活动状态 isActive } useEffect(() => { clientRef.current = socketClient; if (!socketClient?.socket) { socketClient?.start(); // 启动WebSocket连接 } return () => { socketClient?.close(); // 组件卸载时关闭WebSocket连接 }; }, []); // 建立 WebSocket 连接 const connect = () => { const client = clientRef.current; if (client) { client.connect(); // 建立WebSocket连接 } }; // 关闭 WebSocket 连接 const close = () => { const client = clientRef.current; if (client) { client.close(); // 关闭WebSocket连接 } }; // 订阅消息处理程序 const subscribe = (handler: MessageHandler) => { const client = clientRef.current; setIsActive(true); if (client) { client.subscribe(handler); } }; // 取消订阅消息 const unsubscribe = () => { const client = clientRef.current; if (client && isActive) { setIsActive(false); client.unsubscribe(); } }; // 发送消息 const send = (message: string) => { const client = clientRef.current; if (client && client.socket?.readyState === WebSocket.OPEN) { client.send(message); // 发送消息 } else if (client && client.socket?.readyState === WebSocket.CLOSED) { // WebSocket连接未建立或已关闭,需要重新建立连接 client.connect(); // 建立WebSocket连接 } }; return { connect, close, subscribe, unsubscribe, send }; }
在上述代码中,我们使用useRef来保存WebSocketClient实例,使用useState来管理isActive和socketClient状态。通过创建WebSocket连接的URL和accessToken,我们可以在useEffect钩子中实例化WebSocketClient。然后使用useEffect钩子来启动和关闭WebSocket连接,并在组件卸载时关闭连接。
4. 创建WebSocketProvider
为了在整个应用中共享WebSocket连接对象,我们需要创建一个WebSocketProvider组件。这个组件将使用提供者模式将连接对象提供给子组件。
在你的项目中创建一个名为WebSocketProvider.js的文件,并添加以下代码:
import React, { useContext, useEffect } from 'react'; import { useWebSocket } from './useWebSocket'; const WebSocketContext = React.createContext(); export const useWebSocketContext = () => { return useContext(WebSocketContext); }; export const WebSocketProvider = ({ children, accessToken }) => { const webSocket = useWebSocket(accessToken); useEffect(() => { webSocket.connect(); return () => { webSocket.close(); }; }, [webSocket]); return ( <WebSocketContext.Provider value={webSocket}> {children} </WebSocketContext.Provider> ); };
在上述代码中,我们使用useWebSocket钩子来获取WebSocket连接对象,并在useEffect钩子中连接WebSocket,并在组件卸载时关闭连接。然后,我们将连接对象提供给子组件,通过创建一个WebSocketContext.Provider。
5. 在组件中使用共享连接
现在,我们可以在应用的任何组件中使用共享的WebSocket连接了。
假设我们有一个名为ChatComponent的组件,它需要使用WebSocket连接来实现实时聊天功能。在ChatComponent.js文件中,添加以下代码:
import React from 'react'; import { useWebSocketContext } from './WebSocketProvider'; function ChatComponent() { const webSocket = useWebSocketContext(); const sendMessage = () => { if (webSocket) { webSocket.send('Hello, WebSocket!'); } }; return ( <div> <button onClick={sendMessage}>Send Message</button> </div> ); } export default ChatComponent;
在上述代码中,我们使用useWebSocketContext来获取WebSocket连接对象。然后,我们可以在组件中调用send方法来发送消息。
6. 示例应用:实时聊天
我们使用上述代码,创建一个实时聊天应用作为示例。在你的项目中,创建一个名为RealTimeChatApp的文件夹,然后在文件夹中创建以下文件:
- `RealTimeChatApp.js:` 主应用组件
- `ChatComponent.js:` 实时聊天组件
- `WebSocketProvider.js`: `WebSocket`连接提供者
在RealTimeChatApp.js中,添加以下代码:
import React from 'react'; import ChatComponent from './ChatComponent'; import { WebSocketProvider } from './WebSocketProvider'; function RealTimeChatApp() { const accessToken = 'your_access_token'; // 替换为你的访问令牌 return ( <WebSocketProvider accessToken={accessToken}> <div> <h1>Real Time Chat App</h1> <ChatComponent /> </div> </WebSocketProvider> ); } export default RealTimeChatApp;
然后,在ChatComponent.js中,添加以下代码:
import React from 'react'; import { useWebSocketContext } from './WebSocketProvider'; function ChatComponent() { const webSocket = useWebSocketContext(); const [messages, setMessages] = React.useState([]); const [newMessage, setNewMessage] = React.useState(''); React.useEffect(() => { const messageHandler = (message) => { setMessages((prevMessages) => [...prevMessages, message]); }; webSocket.subscribe(messageHandler); return () => { webSocket.unsubscribe(); }; }, [webSocket]); const sendMessage = () => { if (webSocket) { webSocket.send(newMessage); setNewMessage(''); } }; return ( <div> <div> {messages.map((message, index) => ( <div key={index}>{message}</div> ))} </div> <div> <input type="text" value={newMessage} onChange={(e) => setNewMessage(e.target.value)} /> <button onClick={sendMessage}>Send</button> </div> </div> ); } export default ChatComponent;
最后,启动你的应用,访问RealTimeChatApp组件,即可在浏览器中查看实时聊天功能。
7. 总结
本文介绍了如何在React 18应用中使用WebSocket来实现实时通信,并展示了如何通过自定义钩子和提供者模式来共享WebSocket连接对象。通过这种方式,我们可以在多个组件中使用同一个连接对象,从而避免了不必要的连接重复实例化和性能开销。WebSocket在现代实时应用中发挥着重要作用,帮助我们实现更高效的通信和用户体验。
希望本文能够帮助你理解如何在React 18中使用WebSocket,并在应用中实现共享连接的目标。如果你想进一步探索WebSocket的高级用法,可以深入了解WebSocket的各种选项和特性,以满足你的实际需求。
以上就是使用React18和WebSocket构建实时通信功能详解的详细内容,更多关于React18 WebSocket构建实时通信的资料请关注脚本之家其它相关文章!