--- title: 'Socket.io documentation' disqus: JBeanny --- By: Yim Sotharoth Socket.io with Vite ( React JS ) and NodeJS === ## Table of Contents [TOC] ## Folder Structure I firstly create a brand new folder call [socket.io](https://socket.io/) _I want my folder structure to look like this_ ![](https://i.imgur.com/L7yF307.png) ## Client Installation open [socket.io](https://socket.io/) or your preferred folder in terminal then create project :::info _create vite project with the following command_ ```bash= $ npm create vite@latest ``` ***Note I named my frontend as client*** _after the new project is ready to play around with. Then we can start installing the socket.io library. You will need to cd into your project directory for my case I cd into /client_ ```bash= $ npm install socket.io-client ``` ::: ## Let's create the input field and button > In App.jsx I create simple input field and button ```javascript! function App() { return ( <div> <input type="text" placeholder="Message..." /> <button>Send Message</button> </div> ); } export default App; ``` ## Let's create function to send message > In App.jsx still we will create a function calls sendMessage() :::info ***Note that before we create that function we need to import a few things from react and socket.io*** ```javascript! import io from "socket.io-client"; import { useEffect, useState } from "react"; ``` _add these 2 lines in App.jsx_ ::: > After import io from socket.io-client and {useEffect,useState} from 'react' we need to states to handle the message :::info ```javascript! const [message, setMessage] = useState(""); const [messageReceived, setMessageReceived] = useState(""); ``` _message will be used to handle onChange for input field_ _messageReceived will be used to save the message that sent by another client_ ::: > Time to create the function ```javascript! const sendMessage = () => { socket.emit("send_message", { message }); }; ``` :::info we can see the socket.emit("send_message") and send_message is an action name so note that you can use any name you want ::: > Let's modify our input field and button :::info ```javascript! <div> <input type="text" placeholder="Message..." onChange={(e) => setMessage(e.target.value)} /> <button onClick={sendMessage}>Send Message</button> </div> ``` _We added onChange to input field and onClick to the button_ ::: ## Let's handle the message that sent by other client > To do this we need to add the listener for socket.io in the useEffect ```javascript! useEffect(() => { socket.on("receive_message", (data) => { setMessageReceived(data.message); }); }, [socket]); ``` :::info In this useEffect we can see the socket.on("receive_message") which is a listener to listen to the receive_message( you can put any name you want ) action. ::: :::success We have done our first step so let's move to backend part. ::: > Here is the complete code :+1: : ```javascript! import io from "socket.io-client"; import { useEffect, useState } from "react"; const socket = io.connect("http://localhost:8080"); function App() { const [message, setMessage] = useState(""); const [messageReceived, setMessageReceived] = useState(""); const sendMessage = () => { socket.emit("send_message", { message }); }; useEffect(() => { socket.on("receive_message", (data) => { setMessageReceived(data.message); }); }, [socket]); return ( <div> <input type="text" placeholder="Message..." onChange={(e) => setMessage(e.target.value)} /> <button onClick={sendMessage}>Send Message</button> <h1>{messageReceived}</h1> </div> ); } export default App; ``` ## Server Installation > We are going to create a folder name server inside our socket.io folder > so the path will be socket.io/server :::info _create NodeJS project with the following command_ > cd into /server ```bash= $ npm init ``` _after the project is created you will need to install express_ ```bash= $ npm install express ``` _after the new project is ready to play around with. Then we can start installing the socket.io library. You will need to cd into your project directory for my case I cd into /server_ ```bash= $ npm install socket.io ``` ::: ## Let's start building our server > Inside index.js ```javascript! const express = require("express"); const app = express(); const http = require("http"); const cors = require("cors"); app.use(cors()); const server = http.createServer(app); server.listen(8080, () => { console.log("listening on port 8080"); }); ``` :::info By this we can start our server by running on port 8080 _To run the server you can open the terminal and use this command_ ```bash! $ node index.js ``` > or we can use nodemon to restart the server on changes saved _to install nodemon you can use this command_ ```bash! $ npm install nodemon ``` > in package.json you can add this start script into your "scripts" ```javascript! "start": "nodemon index.js" ``` ***By doing this we can start the server with *** ```bash! $ npm start ``` ::: ## Let's put the socket.io into action > first thing first you will need to destruct the Server from socket.io ```javascript! const { Server } = require("socket.io"); ``` > Then you need to create a new io server :::warning ```javascript! const io = new Server(server, { cors: { origin: "http://127.0.0.1:5173", methods: ["GET", "POST"], }, }); ``` This code initializes a new instance of the Server class using the server parameter and an options object as the second argument. The options object includes a cors property, which specifies Cross-Origin Resource Sharing (CORS) options. The cors property is an object that contains two properties: origin and methods. The origin property is set to "http://127.0.0.1:5173", which is the URL of the allowed origin for the CORS requests. The methods property is set to an array of HTTP methods that are allowed for CORS requests, in this case, "GET" and "POST". Overall, this code sets up a server to allow cross-origin requests from a specific origin ("http://127.0.0.1:5173") using only the HTTP methods "GET" and "POST". ::: > After that you need to create a listener which will listen to the connection action :::warning ```javascript! io.on("connection", (socket) => { console.log(`User Connected: ${socket.id}`); socket.on("send_message", (data) => { socket.broadcast.emit("receive_message", data); }); }); ``` This code sets up a socket.io server that listens for incoming socket connections using the "connection" event. When a new client connects, it logs a message to the console with the unique socket.id value associated with that connection. The code then listens for a "send_message" event on the socket object, which is emitted by the client when they want to send a message to the other users in the chat room. When the server receives this event, it broadcasts the message to all other connected sockets except for the sender using the socket.broadcast.emit() method. The data parameter is an object that contains the message content and any other relevant data associated with the message. Note that this code is using the socket.broadcast.emit() method to send the message to all other connected sockets except for the sender. If you want to send the message to all connected sockets, including the sender, you can use the io.emit() method instead. Also, note that this code does not handle any potential errors that may occur during the transmission of the message. In a real-world application, you may want to include error handling to ensure that messages are delivered successfully and that any errors are handled gracefully. ***Important*** ```javascript! socket.broadcast.emit(); ``` _If you use socket.broadcast.emit() the message you sent will be received by everyone_ ::: > Here is the complete code :+1: : ```javascript! const express = require("express"); const app = express(); const http = require("http"); const { Server } = require("socket.io"); const cors = require("cors"); app.use(cors()); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "http://127.0.0.1:5173", methods: ["GET", "POST"], }, }); io.on("connection", (socket) => { console.log(`User Connected: ${socket.id}`); socket.on("send_message", (data) => { socket.broadcast.emit("receive_message", data); }); }); server.listen(8080, () => { console.log("listening on port 8080"); }); ``` ## How to send message to a specific person or group ? > to do this we need to create function to join room ### Let's implement to client > create room state :::info ```javascript! const [room, setRoom] = useState(""); ``` this state will be used to handle room input ::: > joinRoom() function ```javascript! const joinRoom = () => { socket.emit("join_room", room); }; ``` > After that we need to modify our sendMessage() a little ```javascript! const sendMessage = () => { socket.emit("send_message", { message, room }); }; ``` > so in order to let the client able to join room we absolutely need to create a new input field and button :::info ```javascript! <input type="text" placeholder="Room..." onChange={(e) => setRoom(e.target.value)} /> <button onClick={joinRoom}>Join</button> ``` we also implement onChange to our input field and onClick to our button ::: ### Let's implement to server > firstly we need to add join_room action our connection listener ```javascript! socket.on("join_room", (data) => { socket.join(data); }); ``` > and modify our send_message action to this : ```javascript! socket.on("send_message", (data) => { socket.to(data.room).emit("receive_message", data); }); ``` :::info so our connection listener will look like this : ```javascript! io.on("connection", (socket) => { console.log(`User Connected: ${socket.id}`); socket.on("join_room", (data) => { socket.join(data); }); socket.on("send_message", (data) => { socket.to(data.room).emit("receive_message", data); }); }); ``` ::: :::success After implement these code you will be able to use socket.io broadcast and room joining ***Note that broadcast mode and room joining mode have their own usage*** _The differences between these 2 modes :_ ***Broadcast*** ![](https://i.imgur.com/OIj6Dq0.png) > in this case everyone received the same messages ***Room Joining*** ![](https://i.imgur.com/NoV8bzP.png) > in this case 2 clients joined room: 10 and 2 more clients joined room: 11 ::: :::info we can use socket.io to send notification and here is the project repository :spiral_note_pad: noted that these links are not the same as the project above - Client : [Client Repository](https://github.com/JBeanny/questionary-client) - Server : [Server Repository](https://github.com/JBeanny/questionary-server) ::: ### Contact Us - :mailbox: yimsotharoth999@gmail.com - [GitHub](https://github.com/JBeanny) - [Facebook Page](https://www.facebook.com/Metaphorlism) - [Instagram: Metaphorlism](https://www.instagram.com/metaphorlism/)