Node.js 发送太多消息后使用React和Socket.io挂起的聊天应用程序

Node.js 发送太多消息后使用React和Socket.io挂起的聊天应用程序,node.js,reactjs,sockets,socket.io,frontend,Node.js,Reactjs,Sockets,Socket.io,Frontend,我的基本聊天应用程序在发送了7条左右的消息后速度变得非常慢,尽管它在只发送了几条消息时确实可以工作 我在返回的组件中放了一个print语句。我注意到每次我提交聊天信息时,print语句的调用次数是以前的两倍。我假设我的应用程序正在变慢,因为随着我发送更多的消息,我必须以指数形式多次重新呈现DOM 有人知道为什么会这样吗 这是我的React应用程序 import React from 'react'; import io from "socket.io-client"; let

我的基本聊天应用程序在发送了7条左右的消息后速度变得非常慢,尽管它在只发送了几条消息时确实可以工作

我在返回的组件中放了一个print语句。我注意到每次我提交聊天信息时,print语句的调用次数是以前的两倍。我假设我的应用程序正在变慢,因为随着我发送更多的消息,我必须以指数形式多次重新呈现DOM

有人知道为什么会这样吗

这是我的React应用程序

import React from 'react';
import io from "socket.io-client";
let socket = io.connect("localhost:8080");

function App() {
  const [curMessage, setMessage] = React.useState({name: "", message: ""});
  const [messageList, setList] = React.useState([]);

  socket.on("receiveMsg", message => {
    setList([...messageList, message]);
  });

  function handleTyping(e) {
    let target = e.target;
    if (target.id === "name") {
      setMessage({...curMessage, name: target.value});
    } else {
      setMessage({...curMessage, message: target.value});
    }
  }

  function handleSubmit(e) {
    e.preventDefault();
    setList([...messageList, curMessage]);
    setMessage({name: "", message: ""});
    socket.emit("message", curMessage);
  }



  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input id="name" onChange={handleTyping} value={curMessage.name}></input>
        <input id="message" onChange={handleTyping} value={curMessage.message}></input>
        <button>Send Message</button>
      </form>
      <ul>
        {messageList.map(msg => {
          return <li> {msg.name} {msg.message} </li>
        })}
        {console.log("test")}
      </ul>
    </div>
  );
}

export default App;

试着把你的
插座放在(…)
内部使用效果上。可能是在渲染内部执行setState导致了速度减慢

useEffect(() => {
  socket.on("receiveMsg", (message) => {
    setList([...messageList, message]);
  });

  return () => {
    socket.off("receiveMsg");
  };
}, [messageList]);

Chanandrei给出的答案有一个小小的陷阱。让我解释一下

首先让我们看看为什么您的代码有问题
您已经将socket.on listener直接放在组件内部,而不是放在任何挂钩中。这意味着每次组件重新呈现一个新的socket.on侦听器时,都会创建一个新的socket.on侦听器。
  • 您的组件已安装->您将在侦听器上有一个socket.on
  • 您将收到第一条消息->上一个侦听器仍然存在,但由于组件重新呈现,将创建一个新的侦听器
  • 您收到第二条消息->前两个侦听器的组合现在将导致总共4个侦听器
这种模式还在继续

您可能想使用下面给出的代码,但这是错误的方法。 使用[messageList]作为useEffect的第二个参数的问题?? 问题是,您不希望每次更新消息列表时都创建一个新的socket.io侦听器。在组件的生命周期中,应该始终为一个事件创建一个侦听器。因为一旦创建了socket.on侦听器,在侦听该事件的第一次发生后它不会被销毁,所以它只会再次侦听该事件

因此,此类侦听器必须创建一次。在您的情况下,它应该在安装组件时创建

因此,请使用
[]
,空列表作为useEffect的第二个参数。此挂钩相当于componentDidMount

正确代码
useEffect(() => {
  socket.on("receiveMsg", (message) => {
    setList([...messageList, message]);
  });

  return () => {
    socket.off("receiveMsg");
  };
}, [messageList]);
useEffect(() => {
  socket.on("receiveMsg", (message) => {
    setList([...messageList, message]);
  });

  return () => {
    socket.off("receiveMsg");
  };
}, [messageList]);
useEffect(() => {
  socket.on("receiveMsg", (message) => {
    setList([...messageList, message]);
  });

  return () => {
    socket.off("receiveMsg");
  };
}, []);