套接字 IO 发出两次事件

Trí*_*han 0 javascript node.js express socket.io reactjs

情况:

我正在使用 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);
Run Code Online (Sandbox Code Playgroud)

这是我的插座:

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
      });
    });
  });
};
Run Code Online (Sandbox Code Playgroud)

在客户端,聊天页面组件将处理向套接字发送消息和从套接字接收消息:

//_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*/);
};
Run Code Online (Sandbox Code Playgroud)

问题:

每次用户访问聊天页面,socket都会收到connect事件并记录User started chat!到控制台一次,但实际上已经记录了两次,这意味着socket已经处理了两次connect事件。

当_ChatBox收到消息时,它会记录Receive message并显示该消息,但它所做的是记录两次并显示两次消息,这也意味着套接字发出了两次incomeMessage事件。

我想要什么:我希望套接字只处理一次这些事件。

Wil*_*ins 6

看起来你的组件渲染了两次,所以调用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*/);
};
Run Code Online (Sandbox Code Playgroud)

  • 由于 StrictMode,React 会渲染组件两次。此模式基本上通过用力摇晃来检查所有组件中是否存在任何不需要的副作用。如果 useEffect 在第二次安装时导致不同的行为,则说明存在问题,这会导致生产应用程序出现问题。幸运的是,生产应用程序中没有双重渲染(没有严格模式)。这纯粹是 React 帮助您防止 useEffects() 变得更加复杂甚至有问题时出现的潜在问题。 (5认同)