DEV Community

Cover image for Real time chat using Socket.io
Nivedin
Nivedin

Posted on

Real time chat using Socket.io

What are WebSockets?

Socket.IO enables real-time, bidirectional and event-based communication.
It works on every platform, browser or device, focusing equally on reliability and speed.

Socket.IO allows you to bridge the gap between clients and servers, or any other kind of device. It works on every platform, browser or device, focusing equally on reliability and speed. Learn how easy it is to integrate socket functionality into your web app in under ten minutes!

Now let us see how to use Socket.io

The tools that we are going to use are,

  • Nodejs and Express
  • Reactjs
  • and obviously Socket.io ๐Ÿ˜‚

Let us start

We will be building a simple chat app using Nodejs and React.

First initialize our server
npm init

Then install the dependencies
npm install express socket.io

Run the server
node server.js

Let start coding our server now,

const express = require("express");
const socket = require("socket.io");

// App setup
const PORT = 5000;
const app = express();
const server = app.listen(PORT, function () {
  console.log(`Listening on port ${PORT}`);
  console.log(`http://localhost:${PORT}`);
});

// Static files
app.use(express.static("public"));

// Socket setup
const io = socket(server);

io.on("connection", function (socket) {
  console.log("Made socket connection");
  const { roomId } = socket.handshake.query;
  socket.join(roomId);

  // Listen for new messages
  socket.on(NEW_CHAT_MESSAGE_EVENT, (data) => {
    io.in(roomId).emit(NEW_CHAT_MESSAGE_EVENT, data);
  });

  // Leave the room if the user closes the socket
  socket.on("disconnect", () => {
    socket.leave(roomId);
  });
});
});

Enter fullscreen mode Exit fullscreen mode

Once the socket is open, it listens for the event we emit in the React app. The message, that is carried by that event, is then forwarded to all users in the same room by emitting another event. The client picks up the event and adds the message to the array of all messages.

Let us create the front-end now using Reactjs,

Set up the react evironment using create-react-app
npx create-react-app socketio-chat

Install the dependencies
npm install socket.io-client react-router-dom

Start the app,
npm start

We will be creating two pages

  1. Home page - To enter roomId
  2. Chat Page - To chat

App.js

import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

import "./app.css";
import Home from "./pages/Home";
import ChatRoom from "./page/ChatRoom";

function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/:roomId" component={ChatRoom} />
      </Switch>
    </Router>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Home.js

import React,{useState} from "react";
import { Link } from "react-router-dom";


const Home = () => {
  const [roomName, setRoomName] = useState("");

  const handleRoomNameChange = (event) => {
    setRoomName(event.target.value);
  };

  return (
    <div className="home-container">
      <input
        type="text"
        placeholder="Room"
        value={roomName}
        onChange={handleRoomNameChange}
        className="text-input-field"
      />
      <Link to={`/${roomName}`} className="enter-room-button">
        Join room
      </Link>
    </div>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

Chat Room

import React from "react";

import useChatMessage from "../hooks/useChatMessage";

const ChatRoom = (props) => {
  const { roomId } = props.match.params; // Gets roomId from URL
  const { messages, sendMessage } = useChatMessage(roomId); // Creates a websocket and manages messaging
  const [newMessage, setNewMessage] = React.useState(""); // Message to be sent

  const handleNewMessageChange = (event) => {
    setNewMessage(event.target.value);
  };

  const handleSendMessage = () => {
    sendMessage(newMessage);
    setNewMessage("");
  };

  return (
    <div className="chat-room-container">
      <h1 className="room-name">Room: {roomId}</h1>
      <div className="messages-container">
        <ol className="messages-list">
          {messages.map((message, i) => (
            <li
              key={i}
              className={`message-item ${
                message.ownedByCurrentUser ? "my-message" : "received-message"
              }`}
            >
              {message.body}
            </li>
          ))}
        </ol>
      </div>
      <textarea
        value={newMessage}
        onChange={handleNewMessageChange}
        placeholder="Write message..."
        className="new-message-input-field"
      />
      <button onClick={handleSendMessage} className="send-message-button">
        Send
      </button>
    </div>
  );
};

export default ChatRoom;


Enter fullscreen mode Exit fullscreen mode

Let us create a hook to manage the socket and incomming-outgoing messages,

useChatMessage.js

import { useEffect, useRef, useState } from "react";
import socketIOClient from "socket.io-client";

const NEW_CHAT_MESSAGE_EVENT = "newChatMessage"; // Name of the event
const SOCKET_SERVER_URL = "http://localhost:5000";

const useChatMessage= (roomId) => {
  const [messages, setMessages] = useState([]); // Sent and received messages
  const socketRef = useRef();

  useEffect(() => {

    // Creates a WebSocket connection
    socketRef.current = socketIOClient(SOCKET_SERVER_URL, {
      query: { roomId },
    });

    // Listens for incoming messages
    socketRef.current.on(NEW_CHAT_MESSAGE_EVENT, (message) => {
      const incomingMessage = {
        ...message,
        ownedByCurrentUser: message.senderId === socketRef.current.id,
      };
      setMessages((messages) => [...messages, incomingMessage]);
    });

    // Destroys the socket reference
    // when the connection is closed
    return () => {
      socketRef.current.disconnect();
    };
  }, [roomId]);

  // Sends a message to the server that
  // forwards it to all users in the same room
  const sendMessage = (messageBody) => {
    socketRef.current.emit(NEW_CHAT_MESSAGE_EVENT, {
      body: messageBody,
      senderId: socketRef.current.id,
    });
  };

  return { messages, sendMessage };
};

export default useChatMessage;


Enter fullscreen mode Exit fullscreen mode

That's its friends we have created our real-time-chat-app using node-react.
P.S I have skipped the CSS, you guys can add the color to it ๐Ÿ˜

For more information you can visit socket.io official web page Socket.io

Top comments (1)

Collapse
 
sahilatahar profile image
Sahil Atahar

Nice, I have build a Realtime code editor project called Code-Sync.

๐Ÿ”ฎ Features of project:

  • ๐Ÿ’ป Real-time collaboration on code editing across multiple files
  • ๐Ÿš€ Unique room generation with room ID for collaboration
  • ๐ŸŒˆ Syntax highlighting for various file types with auto-language detection
  • ๐Ÿ’ก Auto suggestion based on programming language
  • โฑ๏ธ Instant updates and synchronization of code changes across all files
  • ๐Ÿ“ฃ Notifications for user join and leave events
  • ๐ŸŽจ Multiple themes for personalized coding experience
  • ๐ŸŒ Comprehensive language support for versatile programming
  • ๐Ÿ”  Option to change font size and font family
  • ๐Ÿ‘ฅ User presence list of users currently in the collaboration session, including online/offline status indicators
  • ๐Ÿ“ Open, edit, save, and delete file functionalities
  • ๐Ÿ’พ Option to download files edited within the collaboration session
  • ๐Ÿ’ฌ Group chatting allows users to communicate in real-time while working on code.
  • ๐ŸŽฉ Real-time tooltip displaying users currently editing
  • ๐Ÿš€ Code Execution: Users can execute the code directly within the collaboration environment, providing instant feedback and results.