socket.io chat problems with react

Viewed 310

I am working on a create-react-app project and am trying to incorporate a chat console powered by sockets.io. The problem is that while the chat message is being correctly captured by the front end, sent back to the io server, and then emitted, and the front end is successfully catching those messages, none of the information is passed between users, everything is only happening on the single browser instance. On the backend I have a console logging "new client connected" when someone connects. I noticed that that console is firing a couple of times each time a message is sent, making me think that the problem is somewhere in the react re-rendering process (so the rerenders are triggering a reconnect to the sockets server.)

The code:

Server:

const express = require("express");
const http = require("http");
const socketIo = require("socket.io");

const PORT = process.env.PORT || 4001;
const index = require("./routes/index");

const app = express();
app.use(index);

const server = http.createServer(app);

const io = socketIo(server);

io.on("connection", socket => {
  console.log("New client connected");
  socket.on("chat message", function(msg) {
    console.log("message: " + msg);
    socket.emit("chat message", [msg]);
  });
  socket.on("disconnect", () => console.log("Client disconnected"));
});

server.listen(PORT, () => console.log(`Listening on port ${PORT}`));

app.js (root component)

import React, { useState, useEffect } from "react";
import "./App.css";
import Board from "./components/Board/Board";
import TileCard from "./components/TileCard/TileCard";
import Chat from "./components/Chat/Chat";
import Choice from "./components/Choice/Choice";
import Header from "./components/Header/Header";

import socketIOClient from "socket.io-client";

function App() {
  const socket = socketIOClient("http://127.0.0.1:4001");
  const [textValue, setTextValue] = useState("");
  function handleChatSend(chatMsg) {
    setTextValue(chatMsg);
    socket.emit("chat message", chatMsg);
  }

  useEffect(() => {
    socket.on("chat message", msg => {
      setTextValue(msg);

      console.log("receiving:" + msg);
    });
  }, [textValue]);

  return (
    <>
      <Header />

      <div className="content-container">
        <Board />

        <div className="cards-container col">
          <Chat handleChatSend={handleChatSend} textValue={textValue} />
          <TileCard />
          <Choice />
        </div>
      </div>
    </>
  );
}

export default App;

the chat component:

import React from 'react';
import "./chat.css"

function Chat ({handleChatSend, textValue}) {

   return (
      <div className="chatbox">
         <ul id="messages">
         {textValue !== "" ? <li>{textValue}</li> : null}
         </ul>
    <form onSubmit={event =>{
       event.preventDefault();
       let chatMsg = event.target.elements[0].value;
       handleChatSend(chatMsg)}}>
      <input type="text" id="m" autoComplete="off" /><button type="submit">Send</button>
    </form>
      </div>
   )
}

export default Chat; 
1 Answers

As Omer mentioned in the comment, we need to emit the event using io but not with socket and thats where I was doing the mistake. After following as Omer suggested it works like fantastic and real magic happens with socket

Here how I'm emitting response to client from backend

export default function section(io: socketio.Server, socket: Socket) {
  socket.on("update-section", async (payload: { [Key: string]: any }) => {
    // const query: any = socket.handshake.query;
    const updated = await updateSection({
      ...payload,
      //   ...decodeToken(query?.token),
    });
    io.emit(`update-section-response`, updated);
  });

  socket.on("delete-section", async (sectionId: string) => {
    const deleted = await deleteSection(sectionId);
    io.emit(`delete-section`, deleted);
  });
}
Related