Reputation: 1
I'm emitting socket event from my sever end point & listen that event on react.js client with socket.on() but i found my socket.on event firing multiple times when emit event.I read many question related this issue on stack overflow but did't succeed.
Here relavant code:
server
currentUsers: async function (req, res, next) {
try {
let io = req.app.get("socketio") // get socketio instance
const uoid = req.body.uoid;
const uuid = req.body.uuid || req.decoded.uuid
const beacon_name = req.body.beacon_name
if (uuid !== undefined && beacon_name !== undefined && uoid !== undefined) {
let find = await knex('current_users').where(knex.raw('uuid = ? and uoid = ?', [uuid, uoid])).catch((err) => { return Promise.reject(err) })
if (find.length == 0) {
let result = await knex('current_users').insert({ uuid: uuid, uoid: req.body.uoid, beacon_name: beacon_name, created_at: helper.currentTimeStamp(), in_at: helper.currentTimeStamp(), in: 1,out: 0 }).catch((err) => { return Promise.reject(err) })
console.log('result', result)
let getResult = await knex('users').select('users.id', 'users.name', 'users.email','users.mobile_number', 'users.auth_type', 'users.uuid', 'users.role','current_users.beacon_name','current_users.id as ob_id','beacons_info.beacon_room','current_users.in_at','current_users.out_at').innerJoin('current_users', 'users.uuid', '=', 'current_users.uuid').innerJoin('outlets','outlets.id','=','current_users.uoid').innerJoin('beacons_info', 'beacons_info.name', '=', 'current_users.beacon_name').where(knex.raw('current_users.id = ?',result))
io.emit('in_users',getResult)
res.end()
}
}
} catch (err) {
console.log("err =====>", err)
}
}
client
import React from "react";
import socket from "../../../../utils/socket.io"; // get socket
import EventEmitter from 'events';
class CurrentUsers extends React.Component {
_isMounted = false;
constructor(props) {
super(props);
this.outlet_id = sessionStorage.outlet_id ? sessionStorage.outlet_id : "";
this.selecteId = null;
this.in_users = [];
this.state = {
loading: true,
data: [],
editData: {
name: "",
date: "",
room: ""
}
};
}
componentDidMount() {
console.log("calling component did mount");
this._isMounted = true;
this.setState({ loading: true });
socket.emit('request-current-users-list',this.outlet_id)
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
socket.on('get-current-users-list',(data)=>{
this.setState({ data: data,loading: false})
})
console.log(EventEmitter.listenerCount(socket, 'in_users'));
socket.on('in_users', (data) => {
console.log("=== in ===", data)
})
return (
// template html code
);
}
}
here socket.on(in_users) event firing multiple times.
Upvotes: 0
Views: 2493
Reputation: 737
Somehow it keeps adding the listener each time the socket.on is fired. I tried this:
socket.off('MY_EVENT').on('MY_EVENT', () => doThisOnlyOnce());
I found it on code grepper, and it worked for me.
EDIT: socket.on is fired on each render. so turning it off and on isn't such an efficient way of doing it. A better way would do it would be to run socket.on on first render.
useEffect(()=>{
socket.on('MY_EVENT', () => doThisOnlyOnce());
},[])
Upvotes: 3
Reputation: 287
Put all of your socketio listerners in React inside componentDidMount ,
Its because re-renders, React re-renders multiple times when ever any state changes ,so basically your socketio listerers just keep adding up. That is why you are getting multiple events fired. You just need to add your socketio listeners once , so add your listeners inside componentDidMount()
Upvotes: 2