refactor(websocket): move websocket from state to class property

- Replace `this.state.ws` with `this.websocket` class property for better encapsulation
- Add hot module replacement in index.js for improved development experience

BREAKING CHANGE: WebSocket access pattern changed from state to direct property, may affect external integrations relying on state
This commit is contained in:
sebseb7
2025-09-02 09:00:39 +00:00
parent a8ca291555
commit 7571381b0c
2 changed files with 22 additions and 14 deletions

View File

@@ -5,8 +5,8 @@ class App extends React.Component {
super(props); super(props);
this.state = { this.state = {
counter: 0, counter: 0,
ws: null,
}; };
this.websocket = null;
this.pingInterval = null; this.pingInterval = null;
} }
@@ -19,18 +19,17 @@ class App extends React.Component {
// Connect to WebSocket - use dynamic URL based on current location // Connect to WebSocket - use dynamic URL based on current location
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const websocket = new WebSocket(`${protocol}//${window.location.host}/counter-ws`); this.websocket = new WebSocket(`${protocol}//${window.location.host}/counter-ws`);
this.setState({ ws: websocket });
websocket.onopen = () => { this.websocket.onopen = () => {
console.log('WebSocket connected'); console.log('WebSocket connected');
}; };
websocket.onerror = (error) => { this.websocket.onerror = (error) => {
console.log('WebSocket error:', error); console.log('WebSocket error:', error);
}; };
websocket.onmessage = (event) => { this.websocket.onmessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
if (data.type === 'counter-update') { if (data.type === 'counter-update') {
this.setState({ counter: data.value }); this.setState({ counter: data.value });
@@ -40,14 +39,14 @@ class App extends React.Component {
} }
}; };
websocket.onclose = (event) => { this.websocket.onclose = (event) => {
console.log('WebSocket disconnected', 'Code:', event.code, 'Reason:', event.reason); console.log('WebSocket disconnected', 'Code:', event.code, 'Reason:', event.reason);
}; };
// Send ping every 30 seconds to keep connection alive // Send ping every 30 seconds to keep connection alive
this.pingInterval = setInterval(() => { this.pingInterval = setInterval(() => {
if (websocket.readyState === WebSocket.OPEN) { if (this.websocket.readyState === WebSocket.OPEN) {
websocket.send(JSON.stringify({ type: 'ping' })); this.websocket.send(JSON.stringify({ type: 'ping' }));
} }
}, 30000); }, 30000);
} }
@@ -56,8 +55,8 @@ class App extends React.Component {
if (this.pingInterval) { if (this.pingInterval) {
clearInterval(this.pingInterval); clearInterval(this.pingInterval);
} }
if (this.state.ws) { if (this.websocket) {
this.state.ws.close(); this.websocket.close();
} }
} }
@@ -69,8 +68,8 @@ class App extends React.Component {
.then(data => { .then(data => {
this.setState({ counter: data.value }); this.setState({ counter: data.value });
// Broadcast update via WebSocket // Broadcast update via WebSocket
if (this.state.ws && this.state.ws.readyState === WebSocket.OPEN) { if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
this.state.ws.send(JSON.stringify({ type: 'counter-update', value: data.value })); this.websocket.send(JSON.stringify({ type: 'counter-update', value: data.value }));
} }
}) })
.catch(error => console.error('Error incrementing counter:', error)); .catch(error => console.error('Error incrementing counter:', error));

View File

@@ -3,4 +3,13 @@ import ReactDOM from 'react-dom/client';
import App from './App'; import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root')); const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
const renderApp = () => {
root.render(<App />);
};
renderApp();
if (module.hot) {
module.hot.accept('./App', renderApp);
}