miouri
miouri

Reputation: 409

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?

Upvotes: 0

Views: 56

Answers (1)

millhouse
millhouse

Reputation: 10007

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!

Upvotes: 1

Related Questions