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 (0)