WebSockets provide bidirectional real-time communication.
Custom hook:
1import { useState, useEffect, useRef, useCallback } from "react";23function useWebSocket(url: string) {4 const [isConnected, setIsConnected] = useState(false);5 const [lastMessage, setLastMessage] = useState(null);6 const wsRef = useRef<WebSocket | null>(null);78 const connect = useCallback(() => {9 const ws = new WebSocket(url);10 wsRef.current = ws;1112 ws.onopen = () => setIsConnected(true);13 ws.onclose = () => {14 setIsConnected(false);15 // Auto reconnect16 setTimeout(connect, 3000);17 };18 ws.onmessage = (event) => {19 setLastMessage(JSON.parse(event.data));20 };21 }, [url]);2223 useEffect(() => {24 connect();25 return () => wsRef.current?.close();26 }, [connect]);2728 const sendMessage = useCallback((message: any) => {29 if (wsRef.current?.readyState === WebSocket.OPEN) {30 wsRef.current.send(JSON.stringify(message));31 }32 }, []);3334 return { isConnected, lastMessage, sendMessage };35}
Usage — Chat:
1function Chat() {2 const { isConnected, lastMessage, sendMessage } = useWebSocket("ws://localhost:3000");3 const [messages, setMessages] = useState([]);4 const [input, setInput] = useState("");56 useEffect(() => {7 if (lastMessage) {8 setMessages(prev => [...prev, lastMessage]);9 }10 }, [lastMessage]);1112 const handleSend = () => {13 sendMessage({ type: "message", text: input });14 setInput("");15 };1617 return (18 <div>19 <div className="status">{isConnected ? "Connected" : "Disconnected"}</div>20 <div className="messages">21 {messages.map((msg, i) => (22 <div key={i}>{msg.text}</div>23 ))}24 </div>25 <input value={input} onChange={e => setInput(e.target.value)} />26 <button onClick={handleSend}>Send</button>27 </div>28 );29}
Best practices: