How to Manage Users in Socket.io in Node.js ?
Last Updated :
26 Jul, 2024
Socket.IO is a library that enables real-time, bidirectional, and event-based communication between the browser and the server. Managing users in Socket.io and Node.js typically involves handling user connections, disconnections, and broadcasting messages to specific users or groups of users
Prerequisites:
Approach to managing users in socket.io in Node.js
First, it is important to note that when a new socket is created, it is assigned a unique Id which is retrieved by calling socket.id. This id can be stored within a user object and we can assign an identifier such as a username. For the front end, we will use React, and for the back end node.js and express. Create two folders in your main directory name server(backend) and client(frontend). Socket.on will be an event that will be called whenever needed, and the event is called by the socket.emit, where we call the event and pass the parameter if needed.
Steps to Create Application
Backend Setup
Step 1: Initialize the project using the command
npm init
Step 2 : Install the requires dependencies:
npm i cors express nodemon socket.io http
Project Structure for Backend:

The updated dependencies in package.json file of backend will look like:
{
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"http": "^0.0.1-security",
"nodemon": "^3.0.1",
"socket.io": "^4.7.2"
}
}
Example: Socket.on is used for join whenever a user will join frontend will emit join event and backend will emit message event and send the message that user has joined. Define connection, messaging and other user functions like add, remove and get users.
Node
// Filename - index.js
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const cors = require('cors');
const { addUser, removeUser, getUser,
getUsersInRoom } = require("./users");
const app = express();
const server = http.createServer(app);
const io = socketio(server);
app.use(cors())
io.on("connection", (socket) => {
socket.on('join', ({ name, room }, callback) => {
const { error, user } = addUser(
{ id: socket.id, name, room });
if (error) return callback(error);
// Emit will send message to the user
// who had joined
socket.emit('message', {
user: 'admin', text:
`${user.name},
welcome to room ${user.room}.`
});
// Broadcast will send message to everyone
// in the room except the joined user
socket.broadcast.to(user.room)
.emit('message', {
user: "admin",
text: `${user.name}, has joined`
});
socket.join(user.room);
io.to(user.room).emit('roomData', {
room: user.room,
users: getUsersInRoom(user.room)
});
callback();
})
socket.on('sendMessage', (message, callback) => {
const user = getUser(socket.id);
io.to(user.room).emit('message',
{ user: user.name, text: message });
io.to(user.room).emit('roomData', {
room: user.room,
users: getUsersInRoom(user.room)
});
callback();
})
socket.on('disconnect', () => {
const user = removeUser(socket.id);
if (user) {
io.to(user.room).emit('message',
{
user: 'admin', text:
`${user.name} had left`
});
}
})
})
server.listen(process.env.PORT || 5000,
() => console.log(`Server has started.`));
Node
// Filename - User.js
const users = [];
const addUser = ({ id, name, room }) => {
name = name.trim().toLowerCase();
room = room.trim().toLowerCase();
const existingUser = users.find((user) => {
user.room === room && user.name === name
});
if (existingUser) {
return { error: "Username is taken" };
}
const user = { id, name, room };
users.push(user);
return { user };
}
const removeUser = (id) => {
const index = users.findIndex((user) => {
user.id === id
});
if (index !== -1) {
return users.splice(index, 1)[0];
}
}
const getUser = (id) => users
.find((user) => user.id === id);
const getUsersInRoom = (room) => users
.filter((user) => user.room === room);
module.exports = {
addUser, removeUser,
getUser, getUsersInRoom
};
Frontend Setup:
Step 1: Install react for frontend using this command in terminal
npx create react-app client
Step 2: After react installed, install dependencies for Project inside client folder.
cd client
npm i query-string react-emoji react-router socket.io-client
Project Structure for frontend:

The updated dependencies in package.json file of frontend will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"query-string": "^8.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-emoji": "^0.5.0",
"react-router": "^6.17.0",
"react-scripts": "5.0.1",
"socket.io-client": "^4.7.2",
"web-vitals": "^2.1.4"
},
Step 3: Inside App.js, create routes for the pages join page and chat page and import the components for both pages to display on that route.
Filename: App.js
CSS
/* Filename - Chat/Chat.css */
.outerContainer {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #1A1A1D;
}
.container {
display: flex;
flex-direction: column;
justify-content: space-between;
background: #FFFFFF;
border-radius: 8px;
height: 60%;
width: 35%;
}
@media (min-width: 320px) and (max-width: 480px) {
.outerContainer {
height: 100%;
}
.container {
width: 100%;
height: 100%;
}
}
@media (min-width: 480px) and (max-width: 1200px) {
.container {
width: 60%;
}
}
CSS
/* Filename - InfoBar/InfoBar.css*/
.infoBar {
display: flex;
align-items: center;
justify-content: space-between;
background: #2979FF;
border-radius: 4px 4px 0 0;
height: 60px;
width: 100%;
}
.leftInnerContainer {
flex: 0.5;
display: flex;
align-items: center;
margin-left: 5%;
color: white;
}
.rightInnerContainer {
display: flex;
flex: 0.5;
justify-content: flex-end;
margin-right: 5%;
}
.onlineIcon {
margin-right: 5%;
}
CSS
/* Filename - Input/Input.css */
.form {
display: flex;
border-top: 2px solid #D3D3D3;
}
.input {
border: none;
border-radius: 0;
padding: 5%;
width: 80%;
font-size: 1.2em;
}
input:focus,
textarea:focus,
select:focus {
outline: none;
}
.sendButton {
color: #fff !important;
text-transform: uppercase;
text-decoration: none;
background: #2979FF;
padding: 20px;
display: inline-block;
border: none;
width: 20%;
}
CSS
/* Filename - Join/Join.css*/
html,
body {
font-family: 'Roboto', sans-serif;
padding: 0;
margin: 0;
}
#root {
height: 100vh;
}
* {
box-sizing: border-box;
}
.joinOuterContainer {
display: flex;
justify-content: center;
text-align: center;
height: 100vh;
align-items: center;
background-color: #1A1A1D;
}
.joinInnerContainer {
width: 20%;
}
.joinInput {
border-radius: 0;
padding: 15px 20px;
width: 100%;
}
.heading {
color: white;
font-size: 2.5em;
padding-bottom: 10px;
border-bottom: 2px solid white;
}
.button {
color: #fff !important;
text-transform: uppercase;
text-decoration: none;
background: #2979FF;
padding: 20px;
border-radius: 5px;
display: inline-block;
border: none;
width: 100%;
}
.mt-20 {
margin-top: 20px;
}
@media (min-width: 320px) and (max-width: 480px) {
.joinOuterContainer {
height: 100%;
}
.joinInnerContainer {
width: 90%;
}
}
button:focus {
outline: 0;
}
CSS
/* Filename - Messages/Message/Message.css */
.messageBox {
background: #F3F3F3;
border-radius: 20px;
padding: 5px 20px;
color: white;
display: inline-block;
max-width: 80%;
}
.messageText {
width: 100%;
letter-spacing: 0;
float: left;
font-size: 1.1em;
word-wrap: break-word;
}
.messageText img {
vertical-align: middle;
}
.messageContainer {
display: flex;
justify-content: flex-end;
padding: 0 5%;
margin-top: 3px;
}
.sentText {
display: flex;
align-items: center;
font-family: Helvetica;
color: #828282;
letter-spacing: 0.3px;
}
.pl-10 {
padding-left: 10px;
}
.pr-10 {
padding-right: 10px;
}
.justifyStart {
justify-content: flex-start;
}
.justifyEnd {
justify-content: flex-end;
}
.colorWhite {
color: white;
}
.colorDark {
color: #353535;
}
.backgroundBlue {
background: #2979FF;
}
.backgroundLight {
background: #F3F3F3;
}
CSS
/* Filename Messages/Messages.css */
.messages {
padding: 5% 0;
overflow: auto;
flex: auto;
}
CSS
/* Filename - TextContainer/TextContainer.css */
.textContainer {
display: flex;
flex-direction: column;
margin-left: 100px;
color: rgb(201, 25, 25);
height: 60%;
justify-content: space-between;
}
.activeContainer {
display: flex;
align-items: center;
margin-bottom: 50%;
}
.activeItem {
display: flex;
align-items: center;
}
.activeContainer img {
padding-left: 10px;
}
.textContainer h1 {
margin-bottom: 0px;
}
@media (min-width: 320px) and (max-width: 1200px) {
.textContainer {
display: none;
}
}
JavaScript
// Filename - App.js
import React from 'react';
import Chat from './components/Chat/Chat';
import Join from './components/Join/Join';
import { BrowserRouter as Router, Route }
from "react-router-dom";
const App = () => {
return (
<Router>
<Route path="/" exact component={Join} />
<Route path="/chat" component={Chat} />
</Router>
);
}
export default App;
JavaScript
// Filename - Chat/Chat.js
import React, { useState, useEffect } from "react";
import queryString from "query-string";
import io from 'socket.io-client';
import TextContainer from '../TextContainer/TextContainer';
import Messages from '../Messages/Messages';
import InfoBar from '../InfoBar/InfoBar';
import Input from '../Input/Input';
import "./Chat.css";
let connectionOptions = {
"force new connection": true,
"reconnectionAttempts": "Infinity",
"timeout": 10000,
"transports": ["websocket"]
};
let socket = io.connect('https://localhost:5000', connectionOptions);
const Chat = ({ location }) => {
const [name, setName] = useState('');
const [room, setRoom] = useState("");
const [users, setUsers] = useState('');
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([]);
const ENDPOINT = 'localhost:5000';
useEffect(() => {
const { name, room } = queryString.parse(location.search);
setName(name);
setRoom(room);
socket.emit('join', { name, room }, (error) => {
if (error) {
alert(error);
}
})
return () => {
socket.emit('disconnect');
socket.off();
}
}, [ENDPOINT, location.search]);
useEffect(() => {
socket.on('message', (message) => {
setMessages([...messages, message]);
})
socket.on("roomData", ({ users }) => {
setUsers(users);
});
}, [messages, users])
//Function for Sending Message
const sendMessage = (e) => {
e.preventDefault();
if (message) {
socket.emit('sendMessage', message, () => setMessage(''))
}
}
console.log(message, messages);
return (
<div className="outerContainer">
<div className="container">
<InfoBar room={room} />
<Messages messages={messages} name={name} />
<Input message={message} setMessage={setMessage}
sendMessage={sendMessage} />
</div>
<TextContainer users={users} />
</div>
)
};
export default Chat;
JavaScript
// Filename - InfoBar/InfoBar.js
import React from 'react';
import './InfoBar.css';
const InfoBar = ({ room }) => (
<div className="infoBar">
<div className="leftInnerContainer">
<h3>{room}</h3>
</div>
<div className="rightInnerContainer">
<a href="/">Leave</a>
</div>
</div>
);
export default InfoBar;
JavaScript
// Filename - Input/Input.js
import React from 'react';
import './Input.css';
const Input = ({ setMessage, sendMessage, message }) => (
<form className="form">
<input
className="input"
type="text"
placeholder="Type a message..."
value={message}
onChange={({ target: { value } }) => setMessage(value)}
onKeyPress={event => event.key === 'Enter'
? sendMessage(event) : null}
/>
<button className="sendButton"
onClick={e => sendMessage(e)}>Send</button>
</form>
)
export default Input;
JavaScript
// Filename - Join/Join.js
import React, { useState } from "react";
import { Link } from 'react-router-dom';
import './Join.css';
const Join = () => {
const [name, setName] = useState('');
const [room, setRoom] = useState("");
return (
<div className="joinOuterContainer">
<div className="joinInnerContainer">
<h1 className="heading">Join</h1>
<div>
<input placeholder="Name"
className="joinInput"
type="text"
onChange=
{(event) => setName(event.target.value)} />
</div>
<div>
<input placeholder="Room"
className="joinInput mt-20"
type="text" onChange=
{(event) => setRoom(event.target.value)} />
</div>
<Link onClick={e => (!name || !room) ?
e.preventDefault() : null}
to={`/chat?name=${name}&room=${room}`
}>
<button className={'button mt-20'}
type="submit">Sign In
</button>
</Link>
</div>
</div>
);
};
export default Join;
JavaScript
// Filename - Messages/Message/Message.js
import React from 'react';
import './Message.css';
import ReactEmoji from 'react-emoji';
const Message = ({ message: { text, user }, name }) => {
let isSentByCurrentUser = false;
const trimmedName = name.trim().toLowerCase();
if (user === trimmedName) {
isSentByCurrentUser = true;
}
return (
isSentByCurrentUser
? (
<div className="messageContainer justifyEnd">
<p className="sentText pr-10">{trimmedName}</p>
<div className="messageBox backgroundBlue">
<p className="messageText colorWhite">
{ReactEmoji.emojify(text)}
</p>
</div>
</div>
)
: (
<div className="messageContainer justifyStart">
<div className="messageBox backgroundLight">
<p className="messageText colorDark">
{ReactEmoji.emojify(text)}
</p>
</div>
<p className="sentText pl-10 ">{user}</p>
</div>
)
);
}
export default Message;
JavaScript
// Filename - Messages/Messages.js
import React from 'react';
import Message from './Message/Message';
import './Messages.css';
const Messages = ({ messages, name }) => (
<div>
{messages.map((message, i) => <div key={i}>
<Message message={message} name={name} />
</div>)}
</div>
);
export default Messages;
JavaScript
// Filename TextContainer/TextContainer.js
import React from "react";
import onlineIcon from "../../icons/onlineIcon.png";
import "./TextContainer.css";
const TextContainer = ({ users }) => (
<div className="textContainer">
{users ? (
<div>
<h1>People currently chatting:</h1>
<div className="activeContainer">
<h2>
{users.map(({ name }) => (
<div
key={name}
className="activeItem"
>
{name}
<img
alt="Online Icon"
src={onlineIcon}
/>
</div>
))}
</h2>
</div>
</div>
) : null}
</div>
);
export default TextContainer;
Step to run backend: Go inside the backend folder and open the terminal to write the following command.
npm start
Step to run frontend: Go inside the folder and open the terminal to write the following command.
npm start
Output: Open the browser and type localhost 3000 to see the application running.
Similar Reads
How to manage the packages in Node.js project ?
Node.js is an open-source, cross-platform, back-end JavaScript runtime environment built on the V8 engine and executes the JavaScript code outside the browser. When working on a project in Node.js, you may write code to achieve a specific functionality or to solve a particular problem. There are som
6 min read
How to List all Users in the Mongo Shell
In MongoDB, user management is an essential aspect of database administration, allowing administrators to control access and permissions for different users. The Mongo Shell provides a powerful interface to interact with MongoDB including managing users. In this article, we'll explore how to list al
3 min read
Difference between socket.io and Websockets in Node.js
WebSocket is the correspondence Convention which gives the bidirectional correspondence between the Customer and the Worker over a TCP association, WebSocket stays open constantly, so they permit continuous information move. At the point when customers trigger the solicitation to the Worker it doesn
4 min read
How to build Hostel Management System using Node.js ?
In this article, we are going to create a Hostel Management System. A Hostel Management System is used to manage the record of students of a college to which the college provides a hostel, where a college can view all the student data including their names, roll number, date of birth, city, phone nu
9 min read
How to Build User Management System Using NodeJS?
A User Management System is an essential application for handling user accounts and information. It involves creating, reading, updating, and deleting user accounts, also known as CRUD operations. In this article, we will walk through how to build a simple User Management System using NodeJS.What We
6 min read
Introduction to Sockets.IO in NodeJS
Socket.IO is a popular library that is used for building real-time web applications. It allows your website and server to talk to each other instantly, making things like live chat and instant updates possible.Socket.IO makes it easy to manage WebSocket connections and events.It works even with olde
6 min read
How to Create a Chat App Using socket.io in NodeJS?
Socket.io is a JavaScript library that enables real-time, bidirectional, event-based communication between the client and server. It works on top of WebSocket but provides additional features like automatic reconnection, broadcasting, and fallback options.What We Are Going to Create?In this article,
5 min read
Node.js socket.connect() Method
The socket.connect() method is an inbuilt application programming interface of class Socket within dgram module which is used to connect the particular server to a particular port and address. Syntax: const socket.connect(port[, address][, callback]) Parameters: This method accepts the following par
3 min read
How to Post Data in MongoDB Using NodeJS?
In this tutorial, we will go through the process of creating a simple Node.js application that allows us to post data to a MongoDB database. Here we will use Express.js for the server framework and Mongoose for interacting with MongoDB. And also we use the Ejs for our front end to render the simple
5 min read
How to Make User an Admin on Discord Server
Quick stepsOpen Discord Application or Web AppGo to your server and click on the server nameClick on Server Settings > Roles > Create RoleName a Role as "Admin"Click on "Permissions"Scroll down to "Advanced Permissions"Enable "Administrator"Click âManage Membersâ and add a user for admin role
6 min read