I am building a simple chat application using react, express, and socket.io.
Every time that client sends the message to the server, the server will broadcast the message back to every user. I have a problem when receiving a message back from the backend server.
Every time user receives a message, the useEffect
will run twice instead of only once.
useEffect(() => {
socket.on("broadcast_msg", (data) => {
setMsg((list) => [...list, data]);
});
}, [socket]);
PS. The backend server emits back to the front-end only once. Thank you for every response :D
Whole Code
import React from "react";
import { useEffect } from "react";
import { useState } from "react";
function Chat(props) {
const { socket, username, room } = props;
const [input, setInput] = useState("");
const [msg, setMsg] = useState([]);
// send msg to server
const send_msg = (e) => {
if (input !== "") {
socket.emit("send_msg", {
room: room,
author: username,
message: input,
});
}
};
// listen to boardcast msg
useEffect(() => {
socket.on("broadcast_msg", (data) => {
setMsg((list) => [...list, data]);
});
}, [socket]);
return (
<div className="chat">
<div className="chat-header"></div>
<div className="chat-body">
{msg.map((data) => {
return (
<>
<h1>{data.author}</h1>
<h1>{data.room}</h1>
<h1>{data.message}</h1>
</>
);
})}
</div>
<div className="chat-footer">
<input
type="text"
placeholder="Enter the message..."
onChange={(e) => {
setInput(e.target.value);
}}
/>
<button onClick={send_msg}>Send</button>
</div>
</div>
);
}
export default Chat;
CodePudding user response:
useEffect(() => {
const eventListener = (data) => {
setMsg((list) => [...list, data]);
};
socket.on("broadcast_msg", eventListener);
return () => socket.off("broadcast_msg", listener);
}, [socket]);
Do with listener. Run useEffect and clean the listener when fired again, this should do the trick. or run only once when mounted.
useEffect(() => {
socket.on("broadcast_msg", (data) => {
setMsg((list) => [...list, data]);
});
}, []);