user10591888
user10591888

Reputation:

Same event emitting multiple times in socket.io-client reactjs

I am creating a chat app in react, expressjs and socket.io. When I click on Send Button, I am emitting an event and listening that event on server side and again emitting another event from server side and listening that event on client side. And I have written the event listening code on componentDidMount. But don't know why my client side calling same event multiple times. Below is my both side code:

Client side

var socketIOClient = require('socket.io-client')('http://localhost:4001');

sendMessageClicked(e) {
    e.preventDefault();
    let message = this.state.originalMessage;

    var data = {
        message: message,
        time: Date.now()
    }

    socketIOClient.emit('send_message',data);
}

componentDidMount() {
    socketIOClient.on('msg',function(result){
        let messageHtml = 'messages working!';
        let messageBox = document.getElementById('messageBox');

        if (messageBox ) {
            messageBox.appendChild(messageHtml);
        }
    })
}

render(){
    return(
        <div>
            <form onSubmit={this.sendMessageClicked}>
                <textarea onChange={this.handleMessageChange} name="originalMessage" value={this.state.originalMessage}></textarea>
                <input type="submit" value="" />
            </form>
        </div>
    );
}

Server side

const app = require('./app');

var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(4001);

io.on('connection',function(socket){
    socket.on('send_message',function(data){
        io.emit('msg',data);
    })
})

Can anyone please help with the same?

Upvotes: 2

Views: 2089

Answers (2)

mukund
mukund

Reputation: 633

In the useEffect() hook, checking if socket connection already exists using socket.current helped me get rid of this problem -

useEffect(() => {
  (async () => {
    if (!socket.current) {
      socket.current = io(`http://localhost:8080/`)
      .on("connect", () => {
        //do something 
      });

      socket.current.on("message", (instance) => {
          //receive message from server 
      });
    }
  })();
});

Upvotes: 1

pprzeb
pprzeb

Reputation: 31

I had the same issue, and I solved it with useEffect hook. in your case it would be (on client side):

useEffect(()=>{
socket.on('msg', (result) => {
    let messageHtml = 'messages working!';
    let messageBox = document.getElementById('messageBox');

    if (messageBox ) {
        messageBox.appendChild(messageHtml);
    })
return function cleanup() {socket.off('msg')}
},[])

I'm sure you could do this also with ComponentDidUpdate or ComponentDidUnmount, but useEffect is eassier.

Upvotes: 3

Related Questions