`I am trying to implement socket.io messaging into my react application, and I’m stuck on getting the sockets to work consistently. The socket only works after recompiling the react app, as in, when I first start up the app and api server, the socket connects but messaging doesn’t work, but after a recompile it works fully as intended. I’m relatively new to react and sockets, so I’m not entirely sure where to look.
I imagine it has something to do either with the api server:
const Koa = require('koa');
const app = new Koa();
const http = require('http');
const { Server } = require('socket.io');
const cors = require('@koa/cors');
app.use(cors({ origin: '*' }));
const server = http.createServer(app.callback());
//instatiate new Server
const io = new Server(server, {
autoConnect: false,
cors: {
origin :"http://localhost:3000",
methods: ["GET", "POST"],
autoConnect: false,
},
});
io.on('connection', (socket) => {
console.log('Socket.IO client connected');
socket.on("join_room", (data)=>{
console.log("room joined: ", data);
socket.join(data);
})
socket.on('message_sent', (data) => {
console.log('Received:', data.message, " in ", data.room);
//socket.broadcast.emit('received_message', data.message); //this is only for sending a message for everyone
socket.to(data.room).emit('received_message', data.message);
});
});
require('./config/draught_services_routes.js')(app);
server.listen(3001, () => {
console.log('Server is running on port 3001');
});
or the Messages.js react component:
import { Box, TextField, Typography, Button } from '@mui/material';
import { Fragment, useState, useEffect } from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:3001');
//just checking if the thing connects right
socket.on('connect', () => {
console.log('Connected to server successfully!');
});
socket.on('connect_error', (error) => {
console.error('Connection error:', error);
});
export default function Inbox({userID}) {
const [message, setMessage] = useState('');
const [room, setRoom] = useState('');
const [messages, setMessages] = useState([]);
const [roomName, setRoomName] = useState("");
const handleSendMessage = () => {
if (message.trim() === '') return;
// Sort the usernames alphabetically
const sortedUsernames = [userID.username, room].sort();
setRoomName(sortedUsernames.join(''));
console.log("SENDING MESSAGE ", message, " to room ", roomName);
socket.emit('message_sent', { message: userID.username + ": " + message, room: roomName });
setMessages((prevMessages) => [...prevMessages, userID.username + ": " + message]);
setMessage('');
};
const handleJoinRoom = () => {
if (room.trim() === '') return;
// Sort the usernames alphabetically
const sortedUsernames = [userID.username, room].sort();
setRoomName(sortedUsernames.join(''));
console.log("JOINING ROOM ", sortedUsernames.join(''));
socket.emit('join_room',sortedUsernames.join(''));
};
useEffect(() => {
console.log('Message received' );
socket.on('received_message', (message) => {
setMessages((prevMessages) => [...prevMessages, message]);
});
return () => {
socket.disconnect();
};
}, []);
return (
<Fragment>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between', // Adjust spacing between the two sections
border: 0,
width: '100%', // Ensure the container spans the full width
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
width: '45%', // Adjust width to your preference
}}
>
<TextField
label="to: "
value={room}
onChange={(e) => setRoom(e.target.value)}
variant="outlined"
style={{ marginBottom: '5px', width: '100%' }}
/>
<Button variant="contained" onClick={handleJoinRoom}>
confirm
</Button>
<TextField
label="Type a message..."
value={message}
onChange={(e) => setMessage(e.target.value)}
variant="outlined"
style={{ marginBottom: '10px', width: '100%' }}
/>
<Button variant="contained" onClick={handleSendMessage} style={{ marginLeft: '10px' }}>
Send
</Button>
</Box>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
width: '45%',
}}
>
<Typography variant="h6"> messages </Typography>
<div style={{ marginBottom: '5px', maxHeight: '200px', overflowY: 'scroll', width: '100%' }}>
{messages.map((msg, index) => (
<Typography key={index} variant="body1" style={{ textAlign: 'left' }}>
{msg}
</Typography>
))}
</div>
</Box>
</Box>
</Fragment>
);
}
I’ve tried to move things around and add a delay to send_message to see if it has something to do with that, but to no avail. I’m not really sure what else I could do. Any general advice is appreciated! `
Benito Sanchez is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.