fix: use useRef for WebSocketContext

The main issue with using states was, previously the websocket never closed
properly on unmount, so multiple connections could be opened.

This was because the useEffect cleanup function was closing an old websocket
(that was initialized to null) instead of the current one.

We could have fixed this by adding `ws` to the useEffect dependency array, but
this was unnecessary since `ws` doesn't affect rendering so we shouldn't use a state.
This commit is contained in:
Haileyesus
2026-01-31 11:35:43 +03:00
parent 8e9f7f0536
commit e65a210cb3

View File

@@ -16,7 +16,7 @@ export const useWebSocket = () => {
};
const useWebSocketProviderState = () => {
const [ws, setWs] = useState(null);
const wsRef = useRef(null);
const [messages, setMessages] = useState([]);
const [isConnected, setIsConnected] = useState(false);
const reconnectTimeoutRef = useRef(null);
@@ -28,8 +28,8 @@ const useWebSocketProviderState = () => {
if (reconnectTimeoutRef.current) {
clearTimeout(reconnectTimeoutRef.current);
}
if (ws) {
ws.close();
if (wsRef.current) {
wsRef.current.close();
}
};
}, []); // Keep dependency array but add proper cleanup
@@ -61,7 +61,7 @@ const useWebSocketProviderState = () => {
websocket.onopen = () => {
setIsConnected(true);
setWs(websocket);
wsRef.current = websocket;
};
websocket.onmessage = (event) => {
@@ -75,7 +75,7 @@ const useWebSocketProviderState = () => {
websocket.onclose = () => {
setIsConnected(false);
setWs(null);
wsRef.current = null;
// Attempt to reconnect after 3 seconds
reconnectTimeoutRef.current = setTimeout(() => {
@@ -93,15 +93,16 @@ const useWebSocketProviderState = () => {
};
const sendMessage = (message) => {
if (ws && isConnected) {
ws.send(JSON.stringify(message));
const socket = wsRef.current;
if (socket && isConnected) {
socket.send(JSON.stringify(message));
} else {
console.warn('WebSocket not connected');
}
};
return {
ws,
ws: wsRef.current,
sendMessage,
messages,
isConnected