Real time chat using Socket.io
Tags: react, node, socket, realtime
Published: 2021-09-07 18:30:33

<h1>What are WebSockets?</h1>

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 😂 

<h2>Let us start </h2>

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);
  });
});
});

```
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

<h2>App.js</h2>

```
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;
```

<h2>Home.js</h2>

```
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;
```

<h2>Chat Room </h2>

```
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;


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

<h2>useChatMessage.js</h2>

```
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;


```

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](https://socket.io)