I’m building a test app that connects to a server via WebSocket. The app crashes when I don’t use the WebSocket.close() function in the cleanup part of the useEffect hook. The app works fine when WebSocket.close() is included, ofc I know I should close connection/clean after using it but error references the some kind of ?object? (Error is listed below). Why does this happen?
I’ve tried to understand the issue, and I wonder if it’s related to something that happens in the background. From what I know, cleanup happens after the render, so it shouldn’t directly impact the rendering or state before the component renders. Is my understanding correct, or am I missing something?
Uncaught runtime errors: ERROR An attempt was made to use an object that is not, or is no longer, usable ./src/CommunicationComponent.jsx/WebSocketComponent/
</socketRef.current.onopen@http://localhost:3000/static/js/bundle.js:191:27 EventHandlerNonNull*./src/CommunicationComponent.jsx/WebSocketComponent/<@http://localhost:3000/static/js/bundle.js:189:7 commitHookEffectListMount@http://localhost:3000/static/js/bundle.js:26115:30
commitPassiveMountOnFiber@http://localhost:3000/static/js/bundle.js:27608:42 commitPassiveMountEffects_complete@http://localhost:3000/static/js/bundle.js:27580:38 commitPassiveMountEffects_begin@http://localhost:3000/static/js/bundle.js:27570:45 commitPassiveMountEffects@http://localhost:3000/static/js/bundle.js:27560:38
flushPassiveEffectsImpl@http://localhost:3000/static/js/bundle.js:29443:32 flushPassiveEffects@http://localhost:3000/static/js/bundle.js:29396:18 ./node_modules/react-dom/cjs/react-dom.development.js/commitRootImpl/<@http://localhost:3000/static/js/bundle.js:29211:13
workLoop@http://localhost:3000/static/js/bundle.js:36363:46 flushWork@http://localhost:3000/static/js/bundle.js:36341:18 performWorkUntilDeadline@http://localhost:3000/static/js/bundle.js:36578:25 EventHandlerNonNull*./node_modules/scheduler/cjs/scheduler.development.js/<@http://localhost:3000/static/js/bundle.js:36614:7
./node_modules/scheduler/cjs/scheduler.development.js@http://localhost:3000/static/js/bundle.js:36664:5 options.factory@http://localhost:3000/static/js/bundle.js:41901:31 __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21
./node_modules/scheduler/index.js@http://localhost:3000/static/js/bundle.js:36679:20 options.factory@http://localhost:3000/static/js/bundle.js:41901:31 __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21
./node_modules/react-dom/cjs/react-dom.development.js/<@http://localhost:3000/static/js/bundle.js:6083:40 ./node_modules/react-dom/cjs/react-dom.development.js@http://localhost:3000/static/js/bundle.js:31842:5 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
__webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./node_modules/react-dom/index.js@http://localhost:3000/static/js/bundle.js:31913:20 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
__webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./node_modules/react-dom/client.js@http://localhost:3000/static/js/bundle.js:31856:28 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
__webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./src/index.js@http://localhost:3000/static/js/bundle.js:298:93 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
__webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 @http://localhost:3000/static/js/bundle.js:42544:56 @http://localhost:3000/static/js/bundle.js:42546:12
Working Client Code:
import React, { useEffect, useRef } from 'react';
export default function WebSocketComponent({ children }) {
const socketRef = useRef(null);
const isEstablish = useRef(false); // Tracks if the WebSocket connection is established
const inputRef = useRef(null); // Ref for the input field
useEffect(() => {
if(!isEstablish.current)
{
socketRef.current = new WebSocket('ws://localhost:8080');
socketRef.current.onopen = () => {
console.log('WebSocket connection established.');
socketRef.current.send('Hello Server!');
isEstablish.current = true; // Mark connection as established
};
socketRef.current.onmessage = (event) => {
console.log('Message from server:', event.data);
};
socketRef.current.onerror = (error) => {
console.error('WebSocket error:', error);
};
socketRef.current.onclose = () => {
console.log('WebSocket connection closed.');
isEstablish.current = false; // Mark connection as closed
};
}
// Cleanup function
return () => {
if (socketRef.current) {
socketRef.current.close(); //it must be here, return a error in other case
isEstablish.current = false;
}
};
}, []);
// Function to send data to the server
const sendToServer = () => {
if (isEstablish.current && socketRef.current.readyState === WebSocket.OPEN) {
const message = inputRef.current.value;
console.log('Sent to server:', message);
socketRef.current.send(message); // Send message only if connection is open
} else {
console.error('WebSocket is not open. Cannot send message.');
}
};
return (
<div>
<h1>WebSocket Example</h1>
<input ref={inputRef} />
<button onClick={sendToServer}>Send</button>
</div>
);
}