#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])