Usman Pervaiz
Usman Pervaiz

Reputation: 493

Child component removing the event listener of socket.io from parent component

I have a React app and I am integrating socket.io in react app. Some of the pages that needs Real Time changes, I use sockets to connect to a room and upon change I emit the messages to that room.

I have a child parent structure in which parent is joining a room and child is joining a separate room. Everything is working perfect. When user disconnects and connect again i have an event on componentDidMount that will join the room automatically when user reconnects to the internet. And on componentWillUnmount I remove that event listener. But What happens is when child component will unmount and upon reconnecting the internet, Parent event that should automatically joins the room of the parent component it doesnt get called. Seems like Child componentWillUnmount also removing the event listener of the parent component. Please let me know how can i fix it and what i am doing wrong.

sockets.js

import openSocket from 'socket.io-client';

let socket = '';
if(typeof window !== "undefined") {

    let connectionUri = "http://"+window.location.hostname+":9001"


    socket = openSocket(connectionUri;

    socket.on('messages', function(data) {
        alert(data);
    });
}

export default socket;

I use the above file in each react component to do the functionality regarding sockets.

parent.js

import React, {Component} from 'react'
import Child1 from '../Child1/Index'
import Child2 from '../Child2/Index'
import socket from '../../../sockets'


export default class Parent extends Component {

    componentDidMount() {
        socket.emit('joinRoom', 'Parent')
        socket.on('changeStatus', (data) => {
            .....
        })
        socket.on('connect', () => {
            socket.emit('joinRoom', 'Parent')
        })
    }

    componentWillUnmount() {
        socket.emit('leaveRoom', 'Parent')
        socket.off('changeStatus')
        socket.off('connect')
    }

    render() {

            switch(this.props.pageValue) {
                case "Child1":
                    return <Child1 .... />
                case "Child2":
                    return <Child2 .... />
                default:
                    return null
            }
    }

}

child.js

import React, {Component} from 'react'
import socket from '../../../sockets'


export default class Parent extends Component {

    componentDidMount() {
        socket.emit('joinRoom', 'Child')
        socket.on('changeStatus', (data) => {
            .....
        })
        socket.on('connect', () => {
            socket.emit('joinRoom', 'Child')
        })
    }

    componentWillUnmount() {
        socket.emit('leaveRoom', 'Child')
        socket.off('changeStatus')
        socket.off('connect')
    }

    render() {
       ......
    }

}

Server.js

client.on('joinRoom', function(room) {
    console.log('Connected to Room:', room);
    client.join(room);
});

client.on('leaveRoom', function(room) {
    console.log('Leaving Room:', room);
    client.leave(room);
});

So when the socket.off('connect') called for Child1/Child2. It seems Parent connect event listener also gets removed.

Please let me know if you guys have any questions. Sorry for the bad english

Upvotes: 2

Views: 4387

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84912

Calling socket.off with just the event name causes it to unsubscribe all callbacks for that event. You need to specify which callback to unsubscribe, so that others can remain.

componentDidMount() {
  socket.emit('joinRoom', 'Child')
  socket.on('changeStatus', this.onChangeStatus);
  socket.on('connect', this.onConnect);
}

onChangeStatus(data) {
 ...
}

onConnect() {
  socket.emit('joinRoom', 'Child')
}

componentWillUnmount() {
  socket.emit('leaveRoom', 'Child')
  socket.off('changeStatus', this.onChangeStatus);
  socket.off('connect', this.onConnect);

  // instead of:
  // socket.off('changeStatus') 
  // socket.off('connect') 
}

Upvotes: 3

Related Questions