Tones/contexts/WebSocketContext.js

78 lines
2.2 KiB
JavaScript

import React, { createContext, useEffect, useRef, useState } from 'react';
export const WebSocketContext = createContext(null);
export const WebSocketProvider = ({ children }) => {
const ws = useRef(null);
const reconnectInterval = useRef(null);
const reconnectAttempts = useRef(0);
const maxReconnectAttempts = 5;
const [isConnected, setIsConnected] = useState(false);
const [lastMessage, setLastMessage] = useState(null);
const connect = () => {
if (reconnectAttempts.current >= maxReconnectAttempts) {
console.warn('❌ Max reconnect attempts reached. Giving up.');
clearInterval(reconnectInterval.current);
ws.current?.close();
return;
}
console.log(`🔁 Connecting (Attempt ${reconnectAttempts.current + 1}/${maxReconnectAttempts})`);
ws.current = new WebSocket(process.env.EXPO_PUBLIC_WS_URL);
ws.current.onopen = () => {
console.log('✅ WebSocket connected');
setIsConnected(true);
reconnectAttempts.current = 0;
if (reconnectInterval.current) {
clearInterval(reconnectInterval.current);
reconnectInterval.current = null;
}
};
ws.current.onmessage = (e) => {
console.log('📩 Message received:', e.data);
setLastMessage(e.data);
};
ws.current.onerror = (e) => {
console.error('❌ WebSocket error:', e.message);
};
ws.current.onclose = (e) => {
console.log('🔌 WebSocket closed:', e.code, e.reason);
setIsConnected(false);
if (!reconnectInterval.current && reconnectAttempts.current < maxReconnectAttempts) {
reconnectInterval.current = setInterval(() => {
reconnectAttempts.current += 1;
connect();
}, 3000);
}
};
};
useEffect(() => {
connect();
return () => {
clearInterval(reconnectInterval.current);
ws.current?.close();
};
}, []);
const sendMessage = (msg) => {
if (ws.current?.readyState === WebSocket.OPEN) {
ws.current.send(JSON.stringify(msg));
} else {
console.warn('⚠️ WebSocket is not open. Message not sent.');
}
};
return (
<WebSocketContext.Provider value={{ sendMessage, lastMessage, isConnected }}>
{children}
</WebSocketContext.Provider>
);
};