使用React18和WebSocket構(gòu)建實時通信功能詳解
1. 引言
WebSocket是一種在Web應(yīng)用中實現(xiàn)雙向通信的協(xié)議。它允許服務(wù)器主動向客戶端推送數(shù)據(jù),而不需要客戶端發(fā)起請求。在現(xiàn)代的實時應(yīng)用中,WebSocket經(jīng)常用于實時數(shù)據(jù)傳輸、聊天功能、實時通知和多人協(xié)作等場景。在本篇博客中,我們將探索如何在React 18應(yīng)用中使用WebSocket來實現(xiàn)實時通信。
2. 準備工作
在開始之前,我們需要安裝React 18,并確定你已經(jīng)掌握了React Hooks的基本知識。此外,我們還將使用WebSocket的npm包來實現(xiàn)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:') { //如果當(dāng)前是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)); // 創(chuàng)建 WebSocketClient 實例并傳入 URL 和活動狀態(tài) isActive } useEffect(() => { clientRef.current = socketClient; if (!socketClient?.socket) { socketClient?.start(); // 啟動WebSocket連接 } return () => { socketClient?.close(); // 組件卸載時關(guān)閉WebSocket連接 }; }, []); // 建立 WebSocket 連接 const connect = () => { const client = clientRef.current; if (client) { client.connect(); // 建立WebSocket連接 } }; // 關(guān)閉 WebSocket 連接 const close = () => { const client = clientRef.current; if (client) { client.close(); // 關(guān)閉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(); } }; // 發(fā)送消息 const send = (message: string) => { const client = clientRef.current; if (client && client.socket?.readyState === WebSocket.OPEN) { client.send(message); // 發(fā)送消息 } else if (client && client.socket?.readyState === WebSocket.CLOSED) { // WebSocket連接未建立或已關(guān)閉,需要重新建立連接 client.connect(); // 建立WebSocket連接 } }; return { connect, close, subscribe, unsubscribe, send }; }
在上述代碼中,我們使用useRef來保存WebSocketClient實例,使用useState來管理isActive和socketClient狀態(tài)。通過創(chuàng)建WebSocket連接的URL和accessToken,我們可以在useEffect鉤子中實例化WebSocketClient。然后使用useEffect鉤子來啟動和關(guān)閉WebSocket連接,并在組件卸載時關(guān)閉連接。
4. 創(chuàng)建WebSocketProvider
為了在整個應(yīng)用中共享WebSocket連接對象,我們需要創(chuàng)建一個WebSocketProvider組件。這個組件將使用提供者模式將連接對象提供給子組件。
在你的項目中創(chuàng)建一個名為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,并在組件卸載時關(guān)閉連接。然后,我們將連接對象提供給子組件,通過創(chuàng)建一個WebSocketContext.Provider。
5. 在組件中使用共享連接
現(xiàn)在,我們可以在應(yīng)用的任何組件中使用共享的WebSocket連接了。
假設(shè)我們有一個名為ChatComponent的組件,它需要使用WebSocket連接來實現(xiàn)實時聊天功能。在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連接對象。然后,我們可以在組件中調(diào)用send方法來發(fā)送消息。
6. 示例應(yīng)用:實時聊天
我們使用上述代碼,創(chuàng)建一個實時聊天應(yīng)用作為示例。在你的項目中,創(chuàng)建一個名為RealTimeChatApp的文件夾,然后在文件夾中創(chuàng)建以下文件:
- `RealTimeChatApp.js:` 主應(yīng)用組件
- `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;
最后,啟動你的應(yīng)用,訪問RealTimeChatApp組件,即可在瀏覽器中查看實時聊天功能。
7. 總結(jié)
本文介紹了如何在React 18應(yīng)用中使用WebSocket來實現(xiàn)實時通信,并展示了如何通過自定義鉤子和提供者模式來共享WebSocket連接對象。通過這種方式,我們可以在多個組件中使用同一個連接對象,從而避免了不必要的連接重復(fù)實例化和性能開銷。WebSocket在現(xiàn)代實時應(yīng)用中發(fā)揮著重要作用,幫助我們實現(xiàn)更高效的通信和用戶體驗。
希望本文能夠幫助你理解如何在React 18中使用WebSocket,并在應(yīng)用中實現(xiàn)共享連接的目標。如果你想進一步探索WebSocket的高級用法,可以深入了解WebSocket的各種選項和特性,以滿足你的實際需求。
以上就是使用React18和WebSocket構(gòu)建實時通信功能詳解的詳細內(nèi)容,更多關(guān)于React18 WebSocket構(gòu)建實時通信的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React實現(xiàn)導(dǎo)入導(dǎo)出Excel文件
本文主要介紹了React實現(xiàn)導(dǎo)入導(dǎo)出Excel文件,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07react 項目 中使用 Dllplugin 打包優(yōu)化技巧
在用 Webpack 打包的時候,對于一些不經(jīng)常更新的第三方庫,比如 react,lodash,vue 我們希望能和自己的代碼分離開,這篇文章主要介紹了react 項目 中 使用 Dllplugin 打包優(yōu)化,需要的朋友可以參考下2023-01-01