I am attempting to get websockets to work in my React 17 /Node.JS 20 environment. Specifically, I am trying to setup a test in which I call a node.js API, which then uses client.send() to send a message to the connected React client, and have it do a console.log to see it was called.
Below is the code on my node.js server, as well as the functional React component where I setup the client and listen to onmessage.
The issue is that when I trigger the message to be sent on the server, it never is received/recognized on the React app. There are no error messages. The server shows it setups a connection for my test user, and the React app shows that is has established a connection as well.
I am running node.js on my local machine at http://localhost:8080.
What am I missing/why doesn’t this work?
I have create the following websocket.js file:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ noServer: true });
// Define `clients` as a global variable within this module
global.clients = new Map();
const handleNewConnection=(ws, userId)=>{
console.log(`WebSocket connection established for user ${userId}`);
clients.set(userId, ws);
ws.on('message', (message) => {
// ... handle incoming messages from the client (if needed)
});
ws.on('close', () => {
console.log(`WebSocket connection closed for user ${userId}`);
clients.delete(userId);
});
ws.onerror = (error) => {
console.error('WebSocket error:', error);
clients.delete(userId);
};
}
module.exports = {
wss,
handleNewConnection, // Export the function to handle new connections
sendMessageToUser: (userId, message) => {
const client = global.clients.get(userId);
if (client && client.readyState === WebSocket.OPEN) {
console.log('sending...')
client.send(message);
} else {
console.log(`User with ID ${userId} not found or connection is not open`);
// Handle the case where the user is not connected or the connection is closed
}
}
};
In my main node.js index.js, I have the following to connect the websocket server to the http server:
const port = 8080;
const server = app.listen(port, () => {
console.log(`API: listening on port ${port}`);
});
// Attach the WebSocket server to the HTTP server
server.on('upgrade', (request, socket, head) => {
websocketModule.wss.handleUpgrade(request, socket, head, (ws) => {
websocketModule.wss.emit('connection', ws, request);
});
});
Now, within one of the apps main routes, I have the following code to register the new connection with a given userid.
if (!global.clients.has(userid)) {
const ws = new WebSocket('ws://localhost:8080');
ws.on('open', () => {
websocketModule.handleNewConnection(ws, userid);
});
}
In my REACT APP, I have a functional component and I initialize the websocket with the following useEffect code:
useEffect(() =>{
/* INITIALIZE WEBSOCKET CODE TO */
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
console.log('WebSocket connection established');
};
ws.onmessage = (event) => {
console.log('message received!'); // Log the method was called
};
ws.onclose = () => {
console.log('WebSocket connection closed');
};
return () => {
ws.close(); // Clean up the WebSocket connection on component unmount
};
},[])
Finally, I am firing the following code from another API on my node server.
const {sendMessageToUser} = require('../../../websocket');
sendMessageToUser(claims.userid,'testing')