Home > Mobile >  Socket.io and React online users list not updating correctly
Socket.io and React online users list not updating correctly

Time:07-14

I have an online users list for a chat app I'm making. When you log in it displays your username in the "Online Users" section, and this works fine for any amount of users so far. The problem comes when you log out:

  • User 1 logs in and their username is added to the list.
  • User 2 logs in and their username is added to the list.
  • If user 1 logs out first, user 2's name gets removed and user 1's stays on the list, even when there are no logged in users
  • If user 2 logs out first, their name gets removed and it functions as normal.

Here are my sockets in the backend:

const onlineUsers = [];
io.on("connection", (socket) => {
  socket.emit("online_users", onlineUsers);
  socket.join("public_chat");
  socket.in("public_chat").emit("online_users", onlineUsers);
  console.log(onlineUsers);

  socket.on("user_connected", (user) => {
    const userExists = checkUserArray(user, onlineUsers);
    !userExists && onlineUsers.push({ user, id: socket.id });
    console.log(onlineUsers);
    socket.in("public_chat").emit("online_users", onlineUsers);
    socket.emit("online_users", onlineUsers);
    console.log(`${user} is now online.`);
  });

  socket.on("user_disconnected", (user) => {
    console.log(user);
    const userExists = checkUserArray(user, onlineUsers);
    console.log(userExists);
    // finds the user that disconnected and removes them from the array
    if (userExists) {
      onlineUsers.splice(onlineUsers.indexOf(user), 1);
    }
    socket.emit("online_users", onlineUsers);
    socket.in("public_chat").emit("online_users", onlineUsers);
    console.log(onlineUsers);
    console.log(`${user} is now offline.`);
  });
});

Front end:

const [users, setUsers] = useState([]);

useEffect(() => {
    if (Auth.loggedIn()) {
      const { data } = Auth.getUserInfo();
      socket.emit("user_connected", data.username);
    }
  }, []);

useEffect(() => {
    socket.on("online_users", (onlineUsers) => {
      setUsers(onlineUsers);
    });
  });

const logOutHandler = () => {
    const { data } = Auth.getUserInfo();
    console.log(data.username);
    socket.emit("user_disconnected", data.username);
    Auth.logout();
  };

It seems like the first logged in user's name gets "stuck" in the array.

CodePudding user response:

Your array of users have objects that contain the username and the socketid, but when you disconnect a user you use:

      onlineUsers.splice(onlineUsers.indexOf(user), 1);

indexOf is returning -1 because you user is a string and your array if filled with objects, this causes that the splice func always removes the last element in the array

  • Related