'Socket.io/React Chat App - Connection established
i have two components: where I set the username and room and then I have the component where is the send message and displays the conversation.
When I login on the component, I navigate to the component and trigger the connection with the socket:
const handleClick = (e) => {
e.preventDefault();
navigate("/chatroom", { state: { username, room } });
};
I have two issues regarding the connection with the socket:
-I´ve tried to start the connection inside an useEffect():
export default function ChatRoom() {
const [chatMessage, setChatMessage] = useState("");
const [showmsg, setShowMsg] = useState([]);
const [showObj, setShowObj] = useState([]);
const [submited, setSubmited] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
setShowMsg((oldmsg) => [...oldmsg, chatMessage]);
setChatMessage("");
setSubmited(true);
};
const { state } = useLocation(); //to get data from <Home/> component
useEffect(() => {
const socket = io("http://localhost:3000");
//Message from server
socket.on("message", (msg) => {
setShowObj((oldmsg) => [...oldmsg, msg]);
setSubmited(false);
console.log(showObj);
});
//Message to server
socket.emit("chatMessage", {
user: state.username,
text: showmsg[showmsg.length - 1],
}); //pass the last msg
}, [submited]);
ServerSide:
io.on("connection", (socket) => {
//Welcome current user
socket.emit("message", formatMessage("MiouriChat", "Welcome to the chat!"));
//Broadcast when user connects
socket.broadcast.emit(
"message",
formatMessage("MiouriChat", "A user has joined the chat")
);
//Run when clients disconects
socket.on("disconnect", () => {
io.emit("message", formatMessage("MiouriChat", "A user has left the chat"));
});
//Listen to chat message from client
socket.on("chatMessage", (msg) => {
io.emit("message", formatMessage(msg.user, msg.text));
});
});
This way, everytime I submit a msg ([submited] change), the connection is reseted for obvious reason and get the "welcome" messages everytime it reconects.
If I put the connection outside the useEffect(), the connection reseted everytyme I type a letter on the message input (becouse the state updates.)
What is the best solution for this?
Solution 1:[1]
For your initial "welcome" message, you want a useEffect that only runs after the first render of the page as explained in the docs - by specifying an empty dependency array. This is also a really nice place to define the "cleanup" function, where you want to send a "disconnect" message to your server (in fact the cleanup docs even use a chat API as an example!):
useEffect(() => {
const socket = io("http://localhost:3000");
//Message from server
socket.on("message", (msg) => {
setShowObj((oldmsg) => [...oldmsg, msg]);
console.log(showObj);
});
return () => {
socket.emit("disconnect"); // cleanly disconnect from server
};
}, []); // <- Empty dependency array === only runs after initial render
That solves the "welcome message" and "disconnect" problems, and you no longer need the submited state variable. I can't really help you with the rest, but again I commend the useEffect documentation to you, particularly the example which is so applicable to your use case!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | millhouse |
