Приложение чата React с сокетом замедляется после отправки 15 сообщений

#node.js #reactjs #express #socket.io

#node.js #реагирует на #экспресс #socket.io

Вопрос:

Я новый разработчик и пытаюсь создать довольно надежный проект react, в этом проекте/веб-сайте есть страница с некоторыми пользовательскими вкладками, и одна из этих вкладок-чат. Этот чат использует сокет для связи с сервером. Проблема в том, что после отправки примерно 15-20 сообщений все клиенты, получающие сообщение в чате, будут зависать в течение длительного периода времени. Вот как я внедряю сокет в свой клиент react.

У меня есть служебный файл под названием socket.js:

 import io from "socket.io-client"; const SOCKET_URL = "http://localhost:3001"; export const socket = io(SOCKET_URL, { transports : ['websocket'] });  

Внутри компонента react, использующего сокет:

 import {socket} from "../../utils/socket";  // This code runs (I think) only when the chat state variable changes or when I receive a socket update from the server useEffect(()=gt;{  socket.on("chat msg sent",(chatObj)=gt;{  setChat([...chat,chatObj])  }) },[socket,chat])  // This code is being run when someone sends a chat const sendChat = (msg) =gt; {  const socketObj = {name:props.userState.username, content:msg, id,}  console.log(socketObj);  socket.emit("sending chat msg",socketObj)  const clientObj = {name:props.userState.username, content:msg}  setChat([...chat,clientObj]); }  

Вот что возвращает этот компонент react:

 return (  lt;div className="container-fluid p-0 m-0 border border-3 border-danger"gt;  lt;div className="row p-0 m-0"gt;  lt;div className="col-3 border border-primary border-4"gt;lt;h1gt;lt;/h1gt;lt;/divgt;  lt;div className="col-7 border border-info border-4"gt;lt;/divgt;  lt;div className="col-2 border border-success border-4"gt;  lt;div className="tab"gt;  lt;button className="tablinks" onClick={()=gt;setTab('chat')}gt;Chatlt;/buttongt;  lt;button className="tablinks" onClick={()=gt;setTab('characters')}gt;Charlt;/buttongt;  lt;button className="tablinks" onClick={()=gt;setTab('compendium')}gt;Complt;/buttongt;  lt;button className="tablinks" onClick={()=gt;setTab('settings')}gt;Settlt;/buttongt;  lt;/divgt;  lt;div className="tab-content"gt;  {tabContent}  lt;/divgt;  lt;/divgt;  lt;/divgt;  lt;Character/gt;  lt;/divgt;  );  

Когда выбрана вкладка чат, переменная состояния tabContent устанавливается в это:

 setTabContent(  lt;divgt;  lt;ul className="chat"gt;  {chat.map((entry)=gt;{  return(  lt;ligt;  lt;h6gt;{entry.name}lt;/h6gt;  lt;pgt;{entry.content}lt;/pgt;  lt;/ligt;  )  })}  lt;/ulgt;  lt;form onSubmit={(e)=gt;{  e.preventDefault();  sendChat(chatInput);  setChatInput('');  }}gt;  lt;input className="" value={chatInput} onChange={(e)=gt;setChatInput(e.target.value)}/gt;  lt;/formgt;  lt;/divgt; )  

На заднем конце у меня есть файл под названием socketServer.js, и этот файл содержит любое из подключений к сокету, это просто функция, которая экспортируется в файл основного сервера. socketServer.js:

 exports = module.exports = function (io) {  io.on('connection', function (socket) {  io.emit('greeting', 'welcome to our site!');   socket.on('join campaign room',(id)=gt;{  socket.join(id);  console.log("joining the campaign room", id);  });    socket.on('sending chat msg', (socketObj)=gt;{  console.log("cool beans", socketObj);  const chatObj = {name:socketObj.name, content:socketObj.content}  socket.broadcast.to(socketObj.id).emit('chat msg sent',chatObj);  });  }); }  

В целом это работает до тех пор, пока не будет отправлено слишком много сообщений, а затем это становится очень медленным для тех, кто получает сообщение. Я не верю, что это проблема с бэкэндом, я думаю, что это связано с переменными состояния реакции, которые обновляются сокетом, но я могу ошибаться.

Комментарии:

1. Если мой ответ решил ваши проблемы @Carsdan Dvorachek, пожалуйста, не забудьте указать его в качестве принятого ответа.

Ответ №1:

Ваш эффект использования заключается в настройке новых подключений к сокету.ввод-вывод каждый раз, когда вы получаете новую chat переменную, установленную setChat() . Таким образом, после 15 сообщений вы настроили 15 слушателей на событие сокета sending chat msg . В то же время вы не удаляете предыдущие прослушиватели при очистке useEffect.

Вы можете попробовать это и настроить только один прослушиватель для события сокета

 import {socket} from "../../utils/socket";  // This code runs (I think) only when the chat state variable changes or when I receive a socket update from the server useEffect(()=gt;{  const setChat = (chatObj) =gt; {  setChat(oldChat =gt; [...oldChat, chatObj])  }   socket.on("chat msg sent", setChat)   return () =gt; soket.removeListener("chat msg sent", setChat) },[socket])