Logo


How to make chat-app with socket.io in reactjs?


Creating new applications using React and Node.js always requires a certain amount of work before you actually start working on the final solution. In this tutorial you will find everything you need to start from scratch. Develop a Chat Application Using React, Express and Socket.IO


Installing Node.js dependencies


In the begginning, we're going to use Express as the API that will handle every request made by the front-end:

Command is displayed below:

1npm --save express

After installing our core library we can proceed to create the Node file that will execute all the logic of our application. Create a index.js File in the root directory of your back-end project:

1const express = require("express");
2const app = express();
3const http = require("http");
4const server = http.createServer(app);
5const { Server } = require("socket.io");
6const io = new Server(server, {
7  cors: {
8    origin: "http://localhost:3000",
9    methods: ["*"],
10  },
11});
12
13app.get("/", (req, res) => {
14  res.sendFile(__dirname + "/index.html");
15});
16
17let users = [];
18let chat = [];
19const addUser = (user, socketId) => {
20  !users.some((item) => item.user.id === user.id) && users.push({ user, socketId });
21};
22
23const removeUser = (socketId) => {
24  users = users.filter((user) => user.socketId !== socketId);
25};
26
27const logoutUser = (id) => {
28  users = users.filter((item) => item.user.id !== id);
29};
30 
31
32io.on("connection", (socket) => {
33  //when ceonnect
34  console.log("a user connected.");
35  socket.join(socket.id);
36  //take userId and socketId from user
37  socket.on("addUser", (user) => {
38    addUser(user, socket.id);
39    io.emit("getUsers", users);
40  });
41
42  socket.on("logout", (userId) => {
43    logoutUser(userId);
44    io.emit("getUsers", users);
45  });
46
47  //get chat of single user
48  socket.on("getChat", ({ recieverId, senderId }) => {
49    let selectedUserChat = chat.filter((item) => {
50      if (
51        (item.recieverId === recieverId && item.senderId === senderId) ||
52        (item.recieverId === senderId && item.senderId === recieverId)
53      ) {
54        return item;
55      }
56    });
57    let user = users.find((item) => item.user.id === senderId);
58    io.to(user.socketId).emit("chat", selectedUserChat);
59  });
60
61  //send and get message
62  socket.on("sendMessage", (data) => {
63    chat.push({
64      senderId: data.sender,
65      recieverId: data.reciever,
66      message: data.message,
67    });
68    // const user = getUser(data.reciever);
69    // io.to(user.socketId).emit("newMessage", {
70    //   senderId: data.sender,
71    //   recieverId: data.reciever,
72    //   message: data.message,
73    // });
74  });
75
76  //when disconnect
77  socket.on("disconnect", () => {
78    console.log("A user disconnected!")
79    removeUser(socket.id);
80    io.emit("getUsers", users);
81  });
82});
83
84server.listen(5000, () => {
85  console.log("listening on *:5000");
86});

Creating the Front End The first step to create the front end of our applications will be to initialize the React application. You can easily do this with the command:

1npx create-react-app my-app

Now that the code base for react-app is initialized, we can proceed to install the Socket.IO library for our front end. Just use the client library of socket.io with:

1npm i socket.io-client

After installing the library ,we should have to code for front end.

1import React, { useState, useEffect } from "react";
2import io from "socket.io-client";
3import "./App.css";
4import user1ImgPath from "./images/user1.jfif";
5import user2ImgPath from "./images/user2.jfif";
6import { Card, Form, Button } from "react-bootstrap";
7const socket = io.connect("http://localhost:5000");
8function App() {
9  const [users, setUsers] = useState([]);
10  const [input, setInput] = useState("");
11  const [messages, setMessages] = useState([]);
12  const [reciever, setReciever] = useState("");
13  const [isLogedIn, setIsLogedIn] = useState(false);
14  const [logedInUser, setLogedInUser] = useState({
15    id: 0,
16    name: "",
17  });
18
19  //user login
20  let submitLogin = (e) => {
21    e.preventDefault();
22    if (logedInUser.name) {
23      let userId = Math.floor(Math.random() * 100);
24      let newUser = {
25        id: userId,
26        name: logedInUser.name,
27        imgPath: user2ImgPath,
28      };
29      socket.emit("addUser", newUser);
30      setLogedInUser({ ...logedInUser, id: userId });
31      setIsLogedIn(true);
32    }
33  };
34
35  //user logout
36  let userLogout = () => {
37    socket.emit("logout", logedInUser.id);
38    setIsLogedIn(false);
39    setLogedInUser({ id: 0, name: "" });
40  };
41
42  //change handler of login input field
43  let onChangeHandler = (e) => {
44    setLogedInUser({ ...logedInUser, name: e.target.value });
45  };
46
47  //get chat of specific user
48  let getChat = (recieverId, senderId) => {
49    setReciever(recieverId);
50    socket.emit("getChat", { recieverId, senderId });
51  };
52
53  //send message
54  let sendMessage = () => {
55    console.log(reciever, "sdsad", input);
56    if (reciever && input !== "")
57      socket.emit("sendMessage", {
58        reciever,
59        sender: logedInUser.id,
60        message: input,
61      });
62
63    setMessages([
64      ...messages,
65      { senderId: logedInUser.id, recieverId: reciever, message: input },
66    ]);
67    setInput("");
68  };
69
70  socket.on("getUsers", (users) => {
71    setUsers(users);
72  });
73  socket.on("getMessage", (msg) => {
74    setMessages((prev) => {
75      return [
76        ...prev,
77        {
78          senderId: msg.senderId,
79          senderName: msg.senderName,
80          message: msg.message,
81        },
82      ];
83    });
84  });
85
86  socket.on("newMessage", (msg) => {
87    setMessages((prev) => {
88      if (prev.length != 0) {
89        return [
90          ...prev,
91          {
92            senderId: msg.senderId,
93            recieverId: msg.recieverId,
94            message: msg.message,
95          },
96        ];
97      } else {
98        return [msg];
99      }
100    });
101  });
102  socket.on("chat", (chat) => {
103    setMessages(chat);
104  });
105
106  let selectedUserStyle = {
107    color: "black",
108    marginTop: "10px",
109    backgroundColor: "#e9ecef",
110  };
111  return (
112    <div className="">
113      {!isLogedIn && (
114        <Card style={{ width: "18rem" }} className="mx-auto p-2">
115          <Form onSubmit={submitLogin}>
116            <Card.Title className="text-center">Login</Card.Title>
117            <Form.Control
118              type="text"
119              placeholder="Enter Name"
120              onChange={onChangeHandler}
121            />
122            <Button
123              variant="primary"
124              type="submit"
125              className="mt-2 btn btn-primary btn-sm btn-block"
126            >
127              Login
128            </Button>
129          </Form>
130        </Card>
131      )}
132      {isLogedIn && (
133        <div className="container-fluid mt-2 fixed-top">
134          <div className="row">
135            <div className="col-2 vh-100">
136              <div style={{ overflowY: "scroll", height: "100%" }}   className="hide-scrollbar">
137                <p
138                  style={{ backgroundColor: "#198754" }}
139                  className=" rounded-top p-2"
140                >
141                  Users
142                </p>
143                <ul style={{ listStyleType: "none", paddingLeft: "0px" }} >
144                  {users &&
145                    users.map((item) => {
146                      if (logedInUser && logedInUser.id != item.user.id) {
147                        return (
148                          <li
149                            role="button"
150                            className="rounded m-1"
151                            style={
152                              item.user.id == reciever
153                                ? selectedUserStyle
154                                : { marginTop: "10px" }
155                            }
156                            key={item.user.id}
157                            onClick={() =>
158                              getChat(item.user.id, logedInUser.id)
159                            }
160                          >
161                            <img
162                              src={item.user.imgPath}
163                              alt=""
164                              style={{ height: "20%", width: "20%" }}
165                              className="rounded-circle rounded-fluid"
166                            />{" "}
167                            {item.user.name}
168                          </li>
169                        );
170                      }
171                    })}
172                </ul>
173              </div>
174            </div>
175            <div className="col-10 ">
176              <div
177                className="vh-100 border-start"
178                style={{ position: "relative" }}
179              >
180                <div
181                  className="rounded-top p-2 d-flex justify-content-between align-items-center"
182                  style={{ backgroundColor: "#198754" }}
183                >
184                  <p className="m-0">Chat</p>
185                  <p
186                    className="m-0"
187                    onClick={() => {
188                      userLogout();
189                    }}
190                    role="button"
191                  >
192                    Logout
193                  </p>
194                </div>
195                <ul
196                  className="hide-scrollbar"
197                  style={{
198                    listStyleType: "none",
199                    overflowY: "scroll",
200                    height: "100%",
201                  }}
202                >
203                  {messages &&
204                    messages.map((item, index) => {
205                      if (item.senderId == logedInUser.id) {
206                        return (
207                          <li
208                            key={index}
209                            style={{
210                              display: "inline-block",
211                              clear: "both",
212                              backgroundColor: "blue",
213                              padding: "10px",
214                              color: "white",
215                              borderRadius: "30px 10px 10px 40px",
216                              float: "right",
217                              marginBottom: "10px",
218                            }}
219                          >
220                            <strong>{item.message}</strong>
221                          </li>
222                        );
223                      } else {
224                        return (
225                          <li
226                            key={index}
227                            style={{
228                              display: "inline-block",
229                              clear: "both",
230                              float: "left",
231                              backgroundColor: "#f1f1f1",
232                              padding: "10px",
233                              color: "black",
234                              borderRadius: "10px 30px 40px 10px",
235                              marginBottom: "10px",
236                            }}
237                          >
238                            <strong>{item.message}</strong>
239                          </li>
240                        );
241                      }
242                    })}
243                </ul>
244                <div
245                  style={{
246                    position: "absolute",
247                    bottom: 0,
248                    width: "100%",
249                    boxSizing: "border-box",
250                  }}
251                >
252                  <div className="pb-2 d-flex">
253                    <input
254                      type="text"
255                      style={{ width: "100%", padding: "10px" }}
256                      value={input}
257                      onChange={(e) => {
258                        setInput(e.target.value);
259                      }}
260                    />
261                    <button
262                      style={{ width: "100px", padding: "10px" }}
263                      onClick={() => {
264                        sendMessage();
265                      }}
266                    >
267                      send
268                    </button>
269                  </div>
270                </div>
271              </div>
272            </div>
273          </div>
274        </div>
275      )}
276    </div>
277  );
278}
279
280export default App;

About

Moiz is a software engineer from Arid University with a passion for writing tech tutorials and doing coding. I am continously produce JavaScript and other web development technology tutorials in concepts through easy-to-understand explanations written in plain English.I have expertise in next js ,react js ,javascript,html,bootstrap and node js.

Follow him on Twitter

Hassan is a software engineer from kohat university of science and technology with a passion for writing tech tutorials and doing javascript practices on daily basis.I have expertise in next js ,react js ,javascript,html,bootstrap and node js. Problem Solving and making concpets is my strong point.

Follow him on Twitter

Tags

Click to see all tutorials tagged with:

© Copyright 2023 Pak Annonymous | Back To Homepage | Privacy Policy
Share