1

Hello guys i have simple example with sockets:

const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server, {
  cors: {
    origin: "http://localhost:3000",
    methods: ["GET", "POST"],
    credentials: true
  }
});

var userCount = 0;
io.on('connection', function (socket) {
  userCount++;
  io.emit('userCount', { userCount: userCount });

  socket.on('disconnect', function() {
    userCount--;
    io.emit('userCount', { userCount: userCount });
  });

});

and frontend:

  const [userCount, setuserCount] = useState(0);
  socket.on('userCount', function (data) {
    setuserCount(data.userCount);
  });

I dont understand, but it fire so much requests .. And my question is this proper way to work with sockets?

sh4dow
  • 21
  • 6
  • What do you mean "it fire so much requests"? How many? How often? – jfriend00 Jan 01 '21 at 00:10
  • it send every second request , its not metter how members are there it just buming number – sh4dow Jan 01 '21 at 00:27
  • https://webm.red/view/8oOJ.webm @ but when i replace setuserCount(data.userCount); with console.log(data.userCount); it works good any ide why? – sh4dow Jan 01 '21 at 00:28
  • I don't know what that link in your previous comment is for. When I try to view it, I don't get anything useful. – jfriend00 Jan 01 '21 at 00:55
  • in the footer on right side Active: and there is data.usercount, it just showing how socket working too many requests – sh4dow Jan 01 '21 at 01:38
  • Where have you added your socket listener `socket.on('userCount', function (data) {`? Is it directly in your functional component or is it in a useEffect hook? If its directly in your functional component then every time your component renders you'll be adding a new listener which might be causing unexpected issues – Nick Parsons Jan 01 '21 at 01:51

2 Answers2

2

The issue seems to be with your frontend. The following code runs multiple times everytime your component renders:

socket.on('userCount', function (data) {
  setuserCount(data.userCount);
});

This means that you're adding multiple event listener functions for the one userCount event. To fix this, you can use React's useEffect() hook, which you can use to run code once when your component mounts:

import React, {useState, useEffect} from "react";

... 
// Inside your component:
const [userCount, setuserCount] = useState(0);
useEffect(() => {
  const listener = data => setuserCount(data.userCount);
  socket.on('userCount', listener);
  return () => socket.off('userCount', listener);
}, [setuserCount]);

This way your listener will only be added once when your component mounts, and not multiple times. The cleanup function returned from the useEffect hook will also allow you to remove the listener when the component unmounts (thanks @Codebling for this suggestion). Your socket.on callback will still execute multiple times as socket.io will call it whenever your event occurs.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • 1
    Good catch. Nice touch would be removal of listener on unload `useEffect(() => { const listener = (data) => setuserCount(data.userCount); socket.on('userCount', listener); return () => socket.off(listener);})` – Codebling Jan 01 '21 at 02:13
  • 1
    @Codebling thanks for the suggestion. When I was writing the answer I was going to add this but it completely slipped my mind haha. I've added it to my answer now :) – Nick Parsons Jan 01 '21 at 02:27
  • thanks alot guys 4 trying to help, but this didnt solve my problem its still the same... – sh4dow Jan 01 '21 at 14:35
  • 1
    i did a little changes i did solve problem with example u give , the problem was in my code not ur example thanks alot :] – sh4dow Jan 03 '21 at 02:27
  • It looks like ur good with sockets can u have a look at https://stackoverflow.com/questions/65555995/mern-checking-user-online-or-offline-status maybe u can help me.. Thanks – sh4dow Jan 04 '21 at 00:24
0

I have found similar code here (http://sahatyalkabov.com/jsrecipes/#!/backend/who-is-online-with-socketio) and yes, this is the correct way to use sockets. It fires so many requests because every time a user connects and every time a user disconnects a message is fired (including when you reload. when you reload it fires twice, 1 for getting out and 1 for getting back on the site).

MatthewProSkils
  • 364
  • 2
  • 13
  • ye i used this code bellow but it works very weird, it send me a multipe processes and number goin like 0 2 5 10 12 24 ... and when i open more tabs and connect i got only 0 without moving.. – sh4dow Jan 01 '21 at 00:24
  • https://webm.red/view/8oOJ.webm @ but when i replace setuserCount(data.userCount); with console.log(data.userCount); it works good any ide why? – sh4dow Jan 01 '21 at 00:28
  • Hm... Interesting. Try to emit `socket.client.conn.server.clientsCount` as shown here https://stackoverflow.com/questions/10275667/socket-io-connected-user-count (answer 3) – MatthewProSkils Jan 01 '21 at 00:32
  • ye its really weird, i didnt get any results in example u give.. Weird thing is that when i set console.log i return good count but with state this dont work.. I didnt know how to get variable outside in client so i tried with this state example.. Thanks 4 help – sh4dow Jan 01 '21 at 00:42