Socket IO генерирует события дважды - PullRequest
0 голосов
/ 23 мая 2019

Ситуация:

Я настраиваю экспресс-сервер с socket.io и клиент, использующий ReactJS.Это мой сервер:

//... another requirement
const socket = require("./socket");

const app = express();
const server = http.createServer(app);
const port = process.env.PORT || 3000;

//... some parsers ...

routes(app);
socket(server);

server.listen(port);
console.log("Server started on: " + port);

А это мой сокет:

const socketIO = require("socket.io");

const socket = server => {
  const io = socketIO(server);
  const chat = io.of("/chat");
  chat.on("connection", client => {
    console.log("User started chat!");
    client.on("disconnect", () => {
      console.log("User left chat!");
    });

    client.on("sendMessage", msg => {
      const { id, text } = msg;
      console.log(id + " says: " + text);
      client.broadcast.emit("incomingMessage", {
        //... response data
      });
    });
  });
};

В клиенте компонент Страница чата будет обрабатывать отправку сообщения в сокет и получение сообщения из сокета:

//_ChatBox in Chat Page
const _ChatBox = (/*props*/) => {
  const chat = io("http://localhost" + ":3000/chat");

  chat.on("incomingMessage", message => {
    console.log("Receive message");
    //...handle income message
  });

  const sendMessageToSocket = (data) => {
    chat.emit("sendMessage", data);
  };

  return ( /*JSX*/);
};

Проблема:

Каждый раз, когда пользователь заходит на страницу чата, сокет получает событие подключения и регистрирует User started chat! на консоли один раз, но на самом деле он дважды регистрируется, это означает, что сокет обработал событие подключения дважды.

И когда _ChatBox получает сообщение, он регистрирует Receive message и отображает это сообщение, но он дважды регистрирует и отображает сообщение дважды, что также означает, что сокет дважды отправил событиеcomeMessage.

Что я хочу: Я хочу, чтобы сокет обрабатывал эти события только один раз.

1 Ответ

1 голос
/ 23 мая 2019

Похоже, ваш компонент выполняет рендеринг дважды, поэтому дважды вызывается const chat = io("http://localhost" + ":3000/chat");, что дает два сообщения о соединении.

Вы можете использовать хук useEffect(), чтобы подключиться только на первомвизуализации.Передача пустого массива в качестве второго аргумента означает, что эффект будет вызван только один раз:

const _ChatBox = (/*props*/) => {

  useEffect(()=>{
     const chat = io("http://localhost" + ":3000/chat");

    chat.on("incomingMessage", message => {
      console.log("Receive message");
      //...handle income message
     });

     const sendMessageToSocket = (data) => {
      chat.emit("sendMessage", data);
     };
   }, []);


  return ( /*JSX*/);
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...