每当我发送消息时,它都会在反应中多次显示相同的消息

Posted

技术标签:

【中文标题】每当我发送消息时,它都会在反应中多次显示相同的消息【英文标题】:Whenever i send msg it is showing same message multiple times in react 【发布时间】:2021-06-11 04:31:39 【问题描述】:

上面的img显示了问题。您也可以检查右下角的控制台 我正在使用 socket io react 节点开发一对一的聊天网站,表达我面临这个问题,例如:当我先输入 hi 然后 hi 显示 1 次时,当我输入 hii 时,它显示 2 次,当我第三次输入 jo it显示 jo 3 次我该如何解决这个问题这是我的反应代码另外我的消息在另一端没有收到它只显示在发件人页面上

import React,  Component  from 'react';
import  Link,Redirect  from 'react-router-dom';
import UserService from "../services/userservice";
import getUsersFriend from "../services/messageservice";
import io from "socket.io-client";
const SOCKET_IO_URL = "http://localhost:4000/";

export default class Messages extends Component 
    constructor(props)
        super(props)
        this.socket = io(SOCKET_IO_URL)
        this.state = 
            currentUser: UserService.getCurrentUser(),
            isLoading:false,
            userdetails:[],
            show:false,
            username:'',
            message:'',
            socketConnected:false,
            messages:[]
        ;
        this.onTextboxChangeMessage = this.onTextboxChangeMessage.bind(this)
    

    componentDidMount()
        const currentUser=this.state
        this.fetchUser()
        this.socket.on('connect',()=> 
            this.setState( socketConnected : true)
            // console.log("connection")
        )
    

    async fetchUser()
        try
            const currentUser = this.state
            console.log(currentUser)
            const data =  userid : currentUser.user._id 
            console.log(data)
            let user = await getUsersFriend(data)
            this.setState( userdetails: user );
            // console.log(user)
        catch(err)
            console.log(err)
        
    

    showMessageSpace(elementusername)
        this.setState(
            show: true,
            username:elementusername
        );
    

    onTextboxChangeMessage(e)
        this.setState( message:e.target.value)
    

    SendMessage(e,senderid,receiverusername,message,senderusername)
        e.preventDefault();
        e.stopPropagation()
        console.log('event', e)
        const messages =this.state
        if(this.state.socketConnected)
            console.log('if condition test',senderid,receiverusername,message,senderusername )
            this.socket.emit('send',senderid,receiverusername,message,senderusername);
            this.socket.on(`$receiverusername`, (d)=>
                if(this.state[`$receiverusername`]?.length >= 1 )
                    let messageList = this.state[`$receiverusername`]
                    this.setState([`$receiverusername`]:[...messageList,d])
                
                else
                    this.setState([`$receiverusername`]:[d])
                    console.log('else Condition store individual messages', this.state[`$receiverusername`])
                
        
        this.setState(  message:'' )
    

    

    render()
        const  currentUser ,isLoading,userdetails,message,messages = this.state;
        // console.log(messages)
        if (isLoading) 
            return (<div><p>Loading...</p></div>);
        

        if(!currentUser)
            return(
                <div>
                    <Redirect  to='/login' />
                </div>
            )
        
        else
        return(
            <div>
                <h1>Messages</h1>
                <div>
                    <p>Users</p>
                    ' '
                    <ul className="collection">
                        userdetails.map((element) => 
                            return(
                                <div key=element._id>
                                    <li><Link to=`/dashboard/profile/:$element._id`>element.username</Link>' '<input 
                                    type="button" 
                                    id=element._id
                                    value="Message"
                                    onClick=this.showMessageSpace.bind(this,element.username) ></input></li>
                                </div>
                            );
                        )
                        
                    </ul>
                    ' '
                </div>
                ' '
                    <Link to="/dashboard">Dashboard</Link>
                ' '
                <div>
                
                    this.state.show &&
                    (<div>
                        <h2>Username : ' 'this.state.username</h2>
                        ' '
                        <div>
                            <h3>Body</h3>
                            <div>
                                <ul>
                                /*  this.state[`$this.state.username`]?.map((msg,key) => */
                                this.state.username?.length > 0 && this.state[`$this.state.username`]?.map((msg,key) =>
                                    return(<li key=key>msg.senderusername<span>' 'msg.message</span></li>);
                                )
                                
                                </ul>
                            </div>
                        </div>
                        ' '
                        <div>
                            ' '
                            <input 
                            type="text"
                            name="message"
                            value=message
                            onChange=this.onTextboxChangeMessage
                            ></input>
                            <button className='btn btn-info' onClick=(e)=> this.SendMessage(e,currentUser.user._id,this.state.username,this.state.message,currentUser.user.username)>Send</button>
                        </div>
                        ' '
                    </div>)
                    
                </div>
            </div>
        )
        
    

服务器代码:

io.on('connection', (socket) =>  /* socket object may be used to send specific messages to the new connected client */
  console.log('connection established',socket.id);
  socket.on('send', (data)=>
    console.log("Receive data from single username",data)
     io.emit('message',data)
     socket.on('message',data => 
        console.log("private")
        io.to(data.receiverid).emit('message',data)
     )
  );
  
  socket.on('disconnected',()=>
    console.log("disconnect")
  )
);

【问题讨论】:

【参考方案1】:

这是因为您每次发送消息时都会为套接字分配另一个新回调。

移动这部分:

this.socket.on(`$receiverusername`, (d)=>
  if(this.state[`$receiverusername`]?.length >= 1 )
    let messageList = this.state[`$receiverusername`]
    this.setState([`$receiverusername`]:[...messageList,d])
 else 
    this.setState([`$receiverusername`]:[d])
    console.log('else Condition store individual messages', 
    this.state[`$receiverusername`])

进入 onconnect 回调:

this.socket.on('connect',()=> 
  this.setState( socketConnected : true)

  this.socket.on("message", (d)=>
    if(this.state[`$d.receiverusername`]?.length >= 1 )
      let messageList = this.state[`$d.receiverusername`]
      this.setState([`$receiverusername`]:[...messageList,d.content])
   else 
      this.setState([`$d.receiverusername`]:[d.content])
      console.log('else Condition store individual messages', 
      this.state[`$receiverusername`])
  
)

但在这个变体中,您没有接收者用户名。 所以你应该从你的服务器发送一般的“消息”事件作为包含接收者用户名的对象。

socket.io 文档中详细解释了 on 方法:https://socket.io/docs/v3/listening-to-events/

这里记录了在 onconnect 处理程序中分配 onmessage 回调的模式:

https://socket.io/get-started/chat/#Broadcasting

【讨论】:

它没有显示任何数据,也没有控制台记录任何东西 onconnect 回调:在 componentdidmount 内,我认为它没有渲染 @PratikZinjurde 抱歉,我忘了一件事。请检查更新的答案。 你能检查服务器代码吗,用户没有将消息发送给其他用户,它只显示在自己的标签上 在里面我尝试发送receiverid和senderid,但其他用户没有收到消息

以上是关于每当我发送消息时,它都会在反应中多次显示相同的消息的主要内容,如果未能解决你的问题,请参考以下文章

当用户对消息做出反应时,机器人会在 discord.js 中发送另一条消息

无法通过电子中的渲染器进程发送消息

Discord js v12 如果有人对嵌入做出反应,则发送消息

如何检测某个标签是不是被悬停

当我多次进入聊天室时,让服务器不给我发送相同的消息?

为啥我的消息显示多次?