Reactjs 使用mern stack和socket.io的聊天应用程序在发送超过20条消息后速度变慢

Reactjs 使用mern stack和socket.io的聊天应用程序在发送超过20条消息后速度变慢,reactjs,mongodb,mongoose,socket.io,Reactjs,Mongodb,Mongoose,Socket.io,我正在使用MERN stack和socket.io构建一个实时聊天应用程序。在发送了大约20条消息后,应用程序速度变慢,当其他用户仅在收到发送的消息后才发送另一条消息时,用户无法编写和发送消息。 这是我的聊天组件 import React, {useEffect, useRef, useState} from 'react'; import Messages from "../Messages/Messages"; import axios from 'axios'; imp

我正在使用MERN stack和socket.io构建一个实时聊天应用程序。在发送了大约20条消息后,应用程序速度变慢,当其他用户仅在收到发送的消息后才发送另一条消息时,用户无法编写和发送消息。 这是我的聊天组件

import React, {useEffect, useRef, useState} from 'react';
import Messages from "../Messages/Messages";
import axios from 'axios';
import io from "socket.io-client";

const socket = io('http://localhost:5000/')
function Chat(props) {
    const [messages, setMessages] = useState([])
    const [input, setInput] = useState("")
    useEffect(() => {
        axios.get("http://localhost:5000/")
            .then((res) => {
                setMessages(res.data)
            })
           
        return () => {
            socket.disconnect();
        }
    }, [])
    useEffect(() => {

        socket.on('msgSent', (data) => {
            setMessages([...messages, data])
        })
    }, [messages])
    const renderMessages = () => {
        return (
            messages.map( (message) => {
                return (
                    <Messages key={message._id} sender={message.sender.firstName.concat(message.sender.lastName)}
                              messageText={message.messageText}
                               />
                )
            })
        )
    }
    const sendMessage = (e) => {
        e.preventDefault()
        const message = {
            messageText: input,
        }
        axios.post("http://localhost:5000/", message)
            .then(res => {
                setMessages([...messages, res.data])
                socket.emit('msgSent', res.data)
            })         
    }
    return (       
                {renderMessages()}
                <form onSubmit={(e) => sendMessage(e)}>
                    <input type="text" placeholder="type a message" value={input}
                           onChange={(e) => setInput(e.target.value)}/>
                    <button type="submit"></button>
                </form>                
    );
}
export default Chat;
这是homeRoot,我在这里获取邮件

const express = require("express")
const Router = express.Router()
const Messages = require("../Models/messageModel")
const Users = require("../Models/userModel")
const auth = require("../auth")
Router.get("/",auth,async(req,res)=>{
    try {
        const messages = await Messages.find().populate("sender","firstName lastName")
        res.status(200).send(messages)
    }catch (e) {
        res.status(404).send("messages not found")
    }
})

Router.post("/",auth,async(req,res)=>{

    const user = await Users.findOne({_id:req.userId})
    const message = new Messages({...req.body,sender:user})
    try {
        const savedMessage = await message.save()
        res.status(201).send(savedMessage)

    }catch (e) {
        res.status(404).send("error occured")
    }
})

module.exports = Router

在上面的例子中,您需要像这样使用socket.off()。

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

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

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

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

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

正确代码
谢谢你回答我的问题,我是新来的,尝试编辑我的问题,我希望现在问题更清楚了。问题是,用户只有在收到即将到来的消息后才能编写和发送消息,这会导致应用程序速度减慢。谢谢,更清楚。然而,我仍然不确定发布数据以及通过套接字发送数据的理由是什么。我会跳过帖子,让套接字处理程序将消息放入数据库。跳过GET,让套接字处理程序从广播接收消息。你目前的安排就像发短信和给别人写内容相同的信一样——只需发短信就可以了,不用再寄蜗牛信了。
const express = require("express")
const Router = express.Router()
const Messages = require("../Models/messageModel")
const Users = require("../Models/userModel")
const auth = require("../auth")
Router.get("/",auth,async(req,res)=>{
    try {
        const messages = await Messages.find().populate("sender","firstName lastName")
        res.status(200).send(messages)
    }catch (e) {
        res.status(404).send("messages not found")
    }
})

Router.post("/",auth,async(req,res)=>{

    const user = await Users.findOne({_id:req.userId})
    const message = new Messages({...req.body,sender:user})
    try {
        const savedMessage = await message.save()
        res.status(201).send(savedMessage)

    }catch (e) {
        res.status(404).send("error occured")
    }
})

module.exports = Router
useEffect(() => {
   socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  })

return{
 socket.off("msgSent");
 }
}, [messages])
useEffect(() => {
  socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  });

  return () => {
    socket.off("msgSend");
  };
}, [messages]);
useEffect(() => {
  socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  });

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