In this tutorial, we'll build a basic chat application using Socket.IO and Node.js. Socket.IO is a powerful library that enables real-time, bidirectional communication between web clients and servers. By the end of this tutorial, you'll have a functional chat app where users can join rooms and exchange messages in real-time.
- Basic understanding of JavaScript and Node.js.
- Node.js and npm installed on your system.
1. Create a new directory for your project and navigate to it in your terminal.
2. Initialize a new Node.js project by running:
1npm init -y
1npm install express socket.io
server.js
in your project directory.1import express from "express";
2import { createServer } from "http";
3import { Server } from "socket.io";
4const PORT =process.env.PORT|| 9000;
5const app = express();
6const httpServer = createServer(app);
7const io = new Server(httpServer, {
8 maxHttpBufferSize:1e8,
9 cors:{
10 origin:"*",
11 }
12});
13
14httpServer.listen(PORT,()=>{
15 console.log(`Server is Running on port : ${PORT}`)
16});
17
18
Congratulation! you have sucessfully created a nodejs server.now follow the next step
3. Initialize or listen the connection for message communication
1io.on("connection", (socket) => {
2 console.log("User is connected : "+socket.id);
3
4}
4. After this we will setup frontend and later we will add the remaining code to the server. You just follow the step.
We are going to create a react app using Vite.To create react app using vite follow the step
1) Copy and paste the command in terminal
1yarn create vite
Give your project name here. and press enter after this select React and press enter.
Now select Typescrpt or javascript based on your choice in this tutorial i am going to select javascript because many of you didnot know typescript and hit enter
Congrats! You have sucessfully setup your react project.
2. Open your app in vscode and go to src directory and remove all the existing code inside App.jsx file
1npm install socket.io-client react-scroll-to-bottom
3. Create the main frontent ui.Here you can create your own ui but if you want to use the same ui as i have create just follow and copy the code below.
Create a components follder inside src directory
1import React, { useState } from "react";
2
3const MainTemp = ({
4 onclick,
5 username,
6 onuserchange,
7 room,
8 onroomchange,
9}) => {
10
11
12
13
14 return (
15 <>
16 <div className="container_main">
17 <div className="subcontainer_main">
18 <div className="wrap_main">
19 <div className="heading_main">
20 <h1>WELCOME TO RANDOM CHAT ROOM</h1>
21 </div>
22 <form onSubmit={onclick} className="content_main_cnt">
23 <div className="sub_content_main_cnt">
24 <div className="input_main_cnt">
25 <input onChange={onuserchange} value={username} type="text" name="username" placeholder="Enter Username" required/>
26 </div>
27 <div className="input_main_cnt">
28 {/* <input onChange={onroomchange} value={room} type="text" placeholder="Group Name" /> */}
29 <select value={room} onChange={onroomchange} name="roomSelect" className="selectRoom">
30 <option value="Fun">FUN</option>
31 <option value="Coding">CODING</option>
32 <option value="Random">RANDOM</option>
33 </select>
34
35 </div>
36 <div className="btn_form_maim">
37 <button type="submit">JOIN</button>
38 </div>
39 </div>
40
41 </form>
42 </div>
43
44 </div>
45 </div>
46 </>
47 );
48};
49
50export default MainTemp;
51
Here basically we are creating a form which accepts Your username and that selects the room name from option.
These are the props used here and i have described it properly.
1.App {
2 text-align: center;
3}
4
5.App-logo {
6 height: 40vmin;
7 pointer-events: none;
8}
9
10@media (prefers-reduced-motion: no-preference) {
11 .App-logo {
12 animation: App-logo-spin infinite 20s linear;
13 }
14}
15
16.App-header {
17 background-color: #282c34;
18 min-height: 100vh;
19 display: flex;
20 flex-direction: column;
21 align-items: center;
22 justify-content: center;
23 font-size: calc(10px + 2vmin);
24 color: white;
25}
26
27.App-link {
28 color: #61dafb;
29}
30
31@keyframes App-logo-spin {
32 from {
33 transform: rotate(0deg);
34 }
35 to {
36 transform: rotate(360deg);
37 }
38}
39
40::-webkit-scrollbar {
41 width: 10px;
42}
43
44/* Track */
45::-webkit-scrollbar-track {
46 box-shadow: inset 0 0 5px #0abeef;
47 border-radius: 10px;
48}
49
50/* Handle */
51::-webkit-scrollbar-thumb {
52 background: cyan;
53 border-radius: 10px;
54}
55
56/* Handle on hover */
57::-webkit-scrollbar-thumb:hover {
58 background: transparent;
59}
60
61.container {
62 width: 99%;
63 height: 99vh;
64 background: #282c34;
65 display: flex;
66 justify-content: center;
67 overflow-y: hidden;
68 top: 0;
69 position: absolute;
70 overflow-x: hidden;
71}
72.form_group {
73 background: #282c34;
74 width: 80%;
75 height: 90%;
76 /* background: red; */
77 position: absolute;
78 top: 5%;
79 justify-content: center;
80 display: flex;
81 flex-direction: row;
82 /* background-color: darkcyan; */
83 border-radius: 10px;
84 border: 2px solid cyan;
85 /* box-shadow: 0 0 20px #ececec; */
86 box-shadow: 0 0 20px cyan;
87 flex-wrap: wrap;
88}
89
90.sidebar {
91 content: "";
92 border-radius: 10px;
93 /* background: red; */
94 height: 100%;
95 flex-basis: 35%;
96 width: 100%;
97}
98.main_content {
99 /* background: blue; */
100 border-radius: 10px;
101 flex-basis: 65%;
102 width: 100%;
103 display: flex;
104 /* background: red; */
105 flex-direction: column;
106 position: relative;
107 height: 100%;
108 justify-content: center;
109}
110.main_content_main {
111 /* background: blue; */
112 border-radius: 10px;
113 width: 100%;
114 display: flex;
115 /* background: red; */
116 flex-direction: column;
117 position: relative;
118 height: 100%;
119 justify-content: center;
120}
121.msgtitle {
122 flex-basis: 10%;
123 display: flex;
124 width: 100%;
125 justify-content: center;
126 /* background: red; */
127}
128.fl{
129 width: 100%;
130 height: 100%;
131 display: flex;
132 flex-direction: column;
133
134}
135.fl span{
136 flex-basis: 10%;
137 color: cyan;
138}
139
140.msgtitle .fl h1 {
141 font-family: poppins;
142 color: cyan;
143 text-shadow: 0 0 20px #61dafb;
144 flex-basis: 90%;
145}
146
147.form_components {
148 width: 100%;
149 display: flex;
150 flex-direction: row;
151 justify-content: flex-end;
152 margin-bottom: 5%;
153 position: relative;
154
155 justify-content: center;
156 /* background: blue; */
157
158 margin-top: 10%;
159}
160
161.main_form {
162 flex-basis: 80%;
163
164 border-radius: 0 0 10px 0;
165 display: block;
166 height: 100%;
167 flex-direction: column;
168}
169.form_element {
170 flex-basis: 100%;
171 display: flex;
172 height: 100%;
173 flex-direction: column;
174
175 /* top: 50%; */
176 justify-content: center;
177 position: relative;
178 width: 100%;
179}
180
181.headin {
182 width: 100%;
183 background: rgb(77, 77, 171);
184 flex: 20%;
185 top: 0;
186
187 display: flex;
188 justify-content: center;
189 border-radius: 0 10px 0 0;
190 z-index: 1000;
191}
192
193.headin_main {
194 /* background: red; */
195 width: 100%;
196 flex-basis: 20%;
197 display: flex;
198 flex-direction: column;
199 justify-content: center;
200}
201.headin_main h1 {
202 color: white;
203 text-shadow: 0 0 30px #282c34;
204 text-align: center;
205
206 /* font-size: 2vw; */
207 /* font-size: 5vmin; */
208}
209.form_components input {
210 width: 70%;
211 padding: 12px 10px;
212 border-radius: 10px;
213 border: 1px solid #282c34;
214 box-shadow: 0 0 20px #626262;
215 margin-right: 10px;
216 margin-left: 1%;
217}
218
219.form_components .btnjoin {
220 padding: 10px 15px;
221 justify-self: center;
222 background: palegoldenrod;
223 border-radius: 10px;
224 font-family: poppins;
225 font-size: 15px;
226 border: 1px solid #282c34;
227 font-weight: 600;
228 cursor: pointer;
229 transition: 0.3s;
230}
231.form_components .btnjoin:hover {
232 background: teal;
233 color: white;
234 border: 1px solid white;
235}
236
237.form_components li {
238 list-style: none;
239 background: #ececec;
240 box-shadow: 0 0 10px darkcyan;
241 padding: 15px 0;
242 border-radius: 10px;
243 width: auto;
244 padding: 10px 10px;
245}
246.scroll {
247 overflow-y: hidden;
248 /* overflow-x: hidden; */
249 display: block;
250
251 /* background: red; */
252 /* margin-top: 50%; */
253 top: 20px;
254}
255.wrap {
256 margin: 20px 0;
257 width: 100%;
258 display: flex;
259 /* background: red; */
260 height: 65%;
261}
262
263.fc {
264 bottom: 0;
265 position: absolute;
266}
267
268.sp {
269 width: 100%;
270 height: 100%;
271 overflow-x: hidden;
272 overflow-y: hidden;
273 /* overflow-y: scroll; */
274}
275
276/* @media only screen and (min-width: 600px) {
277
278 .form_group{
279 width: 80%;
280 top: 10%;
281
282
283 }
284 .headin h1{
285 font-size: 35px;
286 }
287} */
288
289/* @media only screen and (min-width: 360px) {
290 .form_group{
291 width: 85%;
292 top: 10%;
293 height: 80%;
294 }
295 .headin h1{
296 font-size: px;
297 }
298
299
300}@media only screen and (min-width: 270px) {
301 .form_group{
302 width: 80%;
303 top: 10%;
304 height: 80%;
305 }
306
307}
308@media only screen and (min-width: 768px) {
309
310 .form_group{
311 width: 50%;
312 height: 80%;
313 }
314
315} */
316
317.message {
318 /* padding: 2px; */
319 min-width: 150px;
320 /* width: auto; */
321 margin-bottom: 15px;
322 background-color: var(--light-color);
323 border-radius: 5px;
324 justify-self: flex-end;
325 background: lightgrey;
326 font-family: poppins;
327 padding: 1px;
328 /* flex: 1 1 2000px; */
329}
330
331.message .meta {
332 font-size: 15px;
333 font-weight: bold;
334 color: var(--dark-color-b);
335 opacity: 0.7;
336 top: 2px;
337 padding: 0 4px;
338 margin-bottom: 0;
339 margin-left: 2px;
340}
341
342.message .meta span {
343 color: #777;
344 text-align: right;
345 float: right;
346 margin-right: 5px;
347 font-size: 10px;
348}
349#you .message .text {
350 color: #777;
351 text-align: right;
352 float: right;
353 margin-right: 5px;
354 padding: 0 19px;
355 font-size: 16px;
356}
357#others .message .text {
358 color: #777;
359 text-align: left;
360 /* float: right; */
361 margin-right: 5px;
362 padding: 0 19px;
363 font-size: 16px;
364}
365#you .message .meta {
366 text-align: left;
367}
368
369.btnsubmit {
370 padding: 10px 15px;
371 justify-self: center;
372 background: palegoldenrod;
373 border-radius: 10px;
374 font-family: poppins;
375 font-size: 15px;
376 border: 1px solid #282c34;
377 font-weight: 600;
378 cursor: pointer;
379 transition: 0.3s;
380 margin-right: 1%;
381}
382.btnsubmit:hover {
383 background: teal;
384 color: white;
385 border: 1px solid white;
386}
387
388/* If the screen size is 601px wide or more, set the font-size of <div> to 80px */
389@media screen and (min-width: 601px) {
390 .headin h1 {
391 font-size: 36px;
392 }
393}
394
395/* If the screen size is 600px wide or less, set the font-size of <div> to 30px */
396
397.main_sidebar {
398 /* background: green; */
399 display: flex;
400 width: 100%;
401 height: 100%;
402 border-radius: 10px;
403 flex-direction: column;
404 /* justify-content: space-between; */
405}
406
407.main_sidebar .group_info {
408 width: 100%;
409 height: 100%;
410 /* background: blue; */
411 border-radius: 10px 0 0 0;
412 flex-basis: 50%;
413}
414.main_sidebar .usersInfo {
415 width: 100%;
416 height: 100%;
417 border-radius: 0 0 0 10px;
418
419 flex-basis: 50%;
420 /* display: hidden; */
421}
422
423.group_info hr {
424 width: 90%;
425 background-color: #ccc;
426 margin-top: 5%;
427}
428/* .main_content{
429 height: 100%;
430
431} */
432
433.grpmain {
434 width: 100%;
435 display: flex;
436 flex-direction: column;
437}
438
439.grpmain .grphead {
440 width: 100%;
441 display: flex;
442 justify-content: center;
443}
444
445.grpmain h1 {
446 font-family: poppins;
447 text-shadow: 0 0 20px #61dafb;
448 color: cyan;
449}
450.grpcnt {
451 display: flex;
452 width: 100%;
453 flex-direction: column;
454 justify-content: center;
455}
456.grpcnt p {
457 text-align: center;
458 color: aqua;
459 font-family: poppins;
460 font-weight: 700;
461 text-shadow: 0 0 10px #61dafb;
462 font-style: italic;
463}
464.grpcnt h2 {
465 text-align: center;
466 color: aqua;
467
468 font-family: poppins;
469 font-style: italic;
470}
471
472.usrmain {
473 width: 100%;
474 display: flex;
475 flex-direction: column;
476 height: 100%;
477}
478
479.usrmain .usrhead {
480 display: flex;
481 flex-basis: 10%;
482 width: 100%;
483 /* background: blue; */
484 height: 100%;
485 margin-left: 15px;
486}
487.usrmain .usrhead h4 {
488 color: #61dafb;
489 text-shadow: 0 0 10px #61dafb;
490}
491.usrmain .usrcnt {
492 height: 100%;
493}
494
495/* Message Body Parts */
496
497.main_message {
498 content: "";
499 height: 100%;
500 /* background: red; */
501 flex-basis: 90%;
502 width: 100%;
503}
504
505.message_in {
506 display: flex;
507 width: 100%;
508 flex-direction: column;
509 position: relative;
510
511 height: 100%;
512}
513
514.message_in .show_messages {
515 content: "";
516 flex-basis: 85%;
517}
518
519.message_in .btn {
520 flex-basis: 13%;
521 height: 100%;
522 width: 100%;
523 /* position: relative; */
524}
525
526.btn .msg_div {
527 width: 100%;
528 display: block;
529 height: 100%;
530
531 /* position: relative; */
532}
533.btn .msg_div .msgcntdiv {
534 width: 100%;
535 display: flex;
536
537 border-radius: 0 0 10px 0;
538 height: 100%;
539 flex-wrap: wrap;
540 border: 1px solid #0abeef;
541 border-radius: 10px;
542 box-shadow: 0 0 10px cyan;
543}
544
545.btn .msg_div .msgcntdiv .input {
546 flex-basis: 60%;
547 width: 100%;
548 height: 100%;
549}
550
551.btn .msg_div .msgcntdiv .input textarea {
552 width: 100%;
553 height: 90%;
554 background: transparent;
555 border: none;
556
557 font-size: 19px;
558
559 padding-left: 10px;
560 line-height: 1.5;
561 display: inline-block;
562 resize: none;
563 max-lines: 3;
564 overflow-y: hidden;
565 color: cyan;
566 /* text-decoration: none; */
567 text-decoration: none;
568 font-family: poppins;
569 text-shadow: 0 0 10px #0abeef;
570}
571
572.btn .msg_div .msgcntdiv .input textarea:focus {
573 border: none;
574 outline: none;
575}
576
577.btn .msg_div .msgcntdiv .attachment {
578 flex-basis: 40%;
579 display: flex;
580 flex-direction: row;
581
582 justify-content: center;
583 width: 100%;
584 text-align: center;
585 /* background: #61dafb; */
586 height: 100%;
587 justify-content: space-evenly;
588}
589
590.at1 {
591 width: 50px;
592 fill: hsl(193, 93%, 50%);
593 /* background: red; */
594 display: flex;
595 padding: 5px;
596 cursor: pointer;
597 justify-content: center;
598 flex-direction: column;
599}
600.at1 button {
601 width: 100%;
602 background: transparent;
603 border: none;
604 cursor: pointer;
605}.at1 label {
606 width: 100%;
607 background: transparent;
608 border: none;
609 cursor: pointer;
610 transition: 0.2s;
611}
612#imginput{
613 position: absolute;
614 opacity: 0;
615 z-index: -1;
616 width: 100%;
617}
618.show_messages {
619 /* background: red; */
620 width: 100%;
621 height: 100%;
622 display: block;
623 position: relative;
624}
625.show_messages .messagecontainer {
626 content: "";
627 width: 100%;
628 /* background: cyan; */
629 height: 98%;
630 display: flex;
631 flex-direction: column;
632 /* overflow-y: scroll; */
633 position: absolute;
634}
635.msgg {
636 width: 100%;
637 display: flex;
638 flex-direction: row;
639 margin-bottom: 10px;
640 /* justify-content: flex-end; */
641}
642.msgboxmain {
643 width: 250px;
644 /* background: red; */
645 display: flex;
646 flex-direction: column;
647text-overflow: clip;
648 margin-left: 10px;
649 /* margin-top: 10px; */
650 border: 2px solid #0abeef;
651 box-shadow: 0 0 20px #0abeef;
652 border-radius: 10px;
653 overflow-wrap: break-word;
654}
655
656.msgboxhead {
657 width: 100%;
658 display: flex;
659 justify-content: space-between;
660 overflow-wrap: break-word;
661}
662
663.msgboxhead p {
664 color: cyan;
665 text-shadow: 0 0 10px cyan;
666 margin: 0 15px;
667 margin-top: 2px;
668 font-family: poppins;
669 font-weight: 700;
670
671}
672.msgboxcnt {
673 width: 100%;
674 display: flex;
675 word-wrap : break-word;
676 overflow-wrap: break-word;
677 overflow: auto;
678 height: 98%;
679 margin-top: 2%;
680}
681.ptime {
682 font-size: 12px;
683}
684.msgboxcnt p {
685 color: cyan;
686 text-shadow: 0 0 10px cyan;
687 padding: 0 5px;
688 text-overflow: clip;
689
690
691}
692.msgboxcnt div{
693 width: 100%;
694 display: flex;
695 flex-direction: column;
696 /* border-radius: 10px; */
697
698}
699.msgboxcnt div img{
700 border-radius: 0 0 0 0;
701}
702.msgboxcnt img {
703 width: 100%;
704 height: 100%;
705 border-radius:0 0 10px 10px;
706
707
708}
709.ld{
710 position: absolute;
711 bottom: 0;
712 z-index: 1000;
713 width: 100%;
714 background: red;
715}
716.usrcnt {
717 content: "";
718
719 flex-basis: 90%;
720 height: 100%;
721 width: 100%;
722
723 position: relative;
724}
725.scrollingdiv {
726 width: 100%;
727 height: 100%;
728 position: relative;
729 overflow-y: scroll;
730 display: flex;
731 flex-direction: column;
732 position: absolute;
733}
734.cntusrmain {
735 width: 98%;
736 display: flex;
737 border: 1px solid #0abeef;
738 justify-content: space-between;
739 margin-left: 1%;
740 margin-bottom: 10px;
741 box-shadow: 0 0 5px #0abeef;
742}
743.cntusrmain .users {
744 font-family: poppins;
745 padding-left: 15px;
746 color: cyan;
747 text-shadow: 0 0 10px #0abeef;
748 font-size: 10px;
749}
750.cntusrmain .logoonline {
751 font-family: poppins;
752 padding-right: 25px;
753 color: cyan;
754 text-shadow: 0 0 10px #0abeef;
755 font-size: 10px;
756}
757
758#you {
759 justify-content: flex-end;
760}
761#others {
762 justify-content: flex-start;
763}
764
765#you .cntusrmain {
766 margin-right: 2%;
767}
768#others .cntusrmain {
769 margin-left: 2%;
770}
771
772/* Designing Main Page */
773
774.container_main {
775 background: #282c34;
776 content: "";
777
778 width: 100%;
779 height: 100vh;
780 display: flex;
781 justify-content: center;
782}
783
784.subcontainer_main {
785 width: 90%;
786 height: 80%;
787 content: "";
788 border: 2px solid #0abeef;
789 box-shadow: 0 0 20px cyan;
790 top: 10%;
791 position: absolute;
792}
793.subcontainer_main .wrap_main {
794 width: 100%;
795 height: 100%;
796 display: flex;
797 flex-direction: column;
798}
799
800.subcontainer_main .wrap_main .heading_main {
801 flex-basis: 20%;
802 width: 100%;
803 height: 100%;
804 display: flex;
805 justify-content: center;
806}
807.subcontainer_main .wrap_main .heading_main h1 {
808 text-align: center;
809 color: cyan;
810 text-shadow: 0 0 30px #0abeef;
811 font-family: poppins;
812 font-weight: 900;
813 font-style: italic;
814
815}
816.subcontainer_main .wrap_main .content_main_cnt {
817 flex-basis: 80%;
818
819 display: flex;
820 flex-direction: row;
821 justify-content: center;
822 width: 100%;
823 height: 100%;
824 position: relative;
825}
826.sub_content_main_cnt {
827 width: 90%;
828 /* background: olive; */
829 display: flex;
830 flex-direction: column;
831 /* position: relative; */
832 justify-content: center;
833 height: 100%;
834
835 /* justify-content: center; */
836}
837
838.input_main_cnt {
839 margin-bottom: 10%;
840 display: flex;
841 width: 100%;
842
843 justify-content: center;
844}
845
846.input_main_cnt input {
847 padding: 10px 0;
848 width: 90%;
849 border-radius: 10px;
850 background: transparent;
851 border: 1px solid #0abeef;
852 box-shadow: 0 0 10px cyan;
853 color: cyan;
854 text-decoration: none;
855 text-shadow: 0 0 10px cyan;
856 padding-left: 10px;
857 font-family: poppins;
858 font-size: 19px;
859}
860.input_main_cnt input:focus {
861 border: none;
862 outline: none;
863 border: 2px solid cyan;
864}
865.input_main_cnt input:hover {
866 box-shadow: 0 0 50px cyan;
867}
868.btn_form_maim {
869 justify-content: center;
870 display: flex;
871 width: 100%;
872}
873.btn_form_maim button {
874 width: 150px;
875 padding: 10px 0;
876 background: transparent;
877 border: 1px solid cyan;
878 color: cyan;
879 font-family: poppins;
880 font-size: 17px;
881 border-radius: 5px;
882 cursor: pointer;
883 letter-spacing: 0.4em;
884 font-weight: 900;
885
886}
887.btn_form_maim button:hover {
888 /* background: #777; */
889 transition: 0.3s;
890 box-shadow: 0 0 50px cyan;
891 color: cyan;
892 text-shadow: 0 0 10px cyan;
893}
894
895.selectRoom{
896
897 padding: 10px 0;
898 width: 90%;
899 border-radius: 10px;
900 background: transparent;
901 border: 1px solid #0abeef;
902 box-shadow: 0 0 10px cyan;
903 color: cyan;
904 text-decoration: none;
905 text-shadow: 0 0 10px cyan;
906 padding-left: 10px;
907 font-family: poppins;
908 font-size: 19px;
909 cursor: pointer;
910
911}
912.selectRoom option{
913 background:#282c34;
914 color: cyan;
915 outline: none;
916 cursor: pointer;
917
918
919}.selectRoom:hover{
920 background:#282c34;
921 color: cyan;
922 cursor: pointer;
923 box-shadow: 0 0 50px cyan;
924
925}
926.grpcnt h2 p a {
927 text-decoration: none;
928 color: darkblue;
929 cursor: pointer;
930}
931
932/*
933.spanuser{
934 width: 100%;
935 display: flex;
936 flex-direction: row;
937} */
938#your{
939
940
941
942 /* background: red; */
943 justify-content: flex-end;
944}
945#othe{
946
947 /* background: blue; */
948 justify-content: flex-start;
949}
950.spanuser{
951 width: 100%;
952 display: flex;
953 justify-content: center;
954 flex-direction: column;
955}
956
957.main_cnt_preview{
958 width: 100%;
959 height: 100%;
960 /* background: red; */
961 position: fixed;
962 top: 0;
963 left: 0;
964 /* opacity:0; */
965 /* display: flex; */
966 justify-content: center;
967 flex-direction: row;
968 transition: display 1s linear;
969
970 /* transition: 0.6s; */
971 display: none;
972
973}
974
975.prev{
976 display: block;
977 /* opacity: 1; */
978
979}
980
981.sub_cnt_preview{
982 width: 79%;
983 height: 89%;
984 background: #777;
985 border-radius: 10px;
986 box-shadow: 0 0 20px #0abeef;
987 margin-top: 2.5%;
988 position: relative;
989 left: 10%;
990}
991.image_preview{
992 width: 100%;
993 height: 100%;
994 border-radius: 10px;
995}
996.image_preview img{
997 width: 100%;
998 height: 100%;
999 object-fit: contain;
1000 border-radius: 10px;
1001}
1002.cancelBtn{
1003 position: absolute;
1004 width: 100%;
1005 /* background: red; */
1006 display: flex;
1007 margin-top: 2%;
1008 justify-content: flex-end;
1009}
1010.cancelBtn button{
1011 margin-right: 2%;
1012 width: 50px;
1013 background: transparent;
1014 border: 2px solid cyan;
1015 box-shadow: 0 0 20px #0abeef;
1016}
1017
1018.cancelBtn button img{
1019 width: 100%;
1020}
1021@media screen and (max-width: 1920px) {
1022 .input_main_cnt input {
1023 width: 60%;
1024 }.selectRoom {
1025 width: 62%;
1026 }
1027 .subcontainer_main {
1028 width: 70%;
1029 }
1030 .input_main_cnt {
1031 margin-bottom: 8%;
1032 }
1033 .fl span{
1034 display: none;
1035 }
1036}
1037
1038@media screen and (max-width: 700px) {
1039 .headin h1 {
1040 font-size: 35px;
1041 }
1042 .sidebar {
1043 display: hidden;
1044 flex-basis: 100%;
1045 height: 50%;
1046 }
1047 .main_content {
1048 flex-basis: 100%;
1049 height: 100%;
1050 }
1051 .form_group {
1052 width: 95%;
1053 }
1054 .sidebar {
1055 display: none;
1056 }
1057 .msgtitle {
1058 font-size: 10px;
1059 text-align: center;
1060 }
1061 .msgboxmain {
1062 width: 200px;
1063 }
1064 .input_main_cnt input {
1065 width: 60%;
1066 }
1067 .selectRoom {
1068 width: 63%;
1069 }
1070 .subcontainer_main {
1071 width: 93%;
1072 }
1073 .input_main_cnt {
1074 margin-bottom: 10%;
1075 }
1076 .subcontainer_main .wrap_main .heading_main h1 {
1077 font-size: 25px;
1078 }
1079 .subcontainer_main {
1080 height: 95%;
1081 top: 0;
1082 }
1083 .fl span{
1084 display: block;
1085 }
1086
1087 .sub_cnt_preview{
1088 width: 94%;
1089 left: 2.5%;
1090 height: 89%;
1091 top: 3.2%;
1092 }
1093
1094}
1095@media screen and (max-width: 350px) {
1096 .headin h1 {
1097 font-size: 30px;
1098 }
1099 .sidebar {
1100 display: hidden;
1101 flex-basis: 100%;
1102 height: 40%;
1103 }
1104 .main_content {
1105 flex-basis: 100%;
1106 height: 60%;
1107
1108 top: 0;
1109 }
1110 .btn .msg_div .msgcntdiv .input {
1111 flex-basis: 50%;
1112 }
1113 .btn .msg_div .msgcntdiv .attachment {
1114 flex-basis: 60%;
1115 }
1116 .fl span{
1117 display: block;
1118 }
1119
1120}
1body {
2 margin: 0;
3 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 sans-serif;
6 -webkit-font-smoothing: antialiased;
7 -moz-osx-font-smoothing: grayscale;
8}
9
10code {
11 font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 monospace;
13}
14
Initialize Your Socket.io client in App.js File
1import "./App.css";
2import React, { useEffect, useState } from "react";
3const { io } = require("socket.io-client");
4
5const socket = io("http://localhost:8000");
6function App() {
7
8 return (
9 <>
10
11 </>
12 );
13}
14
15export default App;
16
Now Go to App.js and Import Your Main.js components over there which you have created beore.
1import "./App.css";
2import React, { useEffect, useState } from "react";
3import Main from "./assets/Components/Main";
4
5const { io } = require("socket.io-client");
6
7const socket = io("http://localhost:8000");
8function App() {
9
10
11 const [username,setUsername] = useState("");
12 const [room,setRoomname] = useState("");
13
14
15 const onclick = (e) => {
16
17 };
18
19
20
21
22 return (
23 <>
24 <div className="conatiner">
25
26 <Main
27 onclick={onclick}
28 value={username}
29 username={username}
30 onroomchange={(e) => {
31 setRoomname(e.target.value);
32 }}
33 onuserchange={(e) => {
34 setUsername(e.target.value);
35 }}
36 room={room}
37 />
38
39
40 </div>
41 </>
42 );
43}
44
45export default App;
46
Here Main components is imported and we have passed the props value like username room name and onchange function. After this just run your project using the below command.
1npm run dev
Now your Main Page will look like this
Now we are going to work with both server and client whenever a user join the chat we are going to emit the join_room using socket.io and emitting the oin_room join_room from client side and getting that response in server side
1 const [isMainPage,setIsMainPage] = useState(true);
2
3
4 const onclick = (e) => {
5 const onclick = (e) => {
6 e.preventDefault();
7 // console.log(username);
8 setIsMainPage(false);
9 const data = {
10 username: username,
11 room: room,
12 id: socket.id,
13 time:
14 new Date(Date.now()).getHours() +
15 ":" +
16 new Date(Date.now()).getMinutes(),
17 userType: "new_user",
18 };
19 socket.emit("join_room", data);
20 };
21
22 };
Here isMainPage basically tells that we are in mainpage and whenever a user join the chat or click on join chat it will become false and chatPage will be displayed
Lets handle that in server side.
Go to Server.js file and copy and paste the following code
1
2//here we are storing all the users
3const users = [];
4
5// Join user to chat
6function userJoin(id, username, room) {
7 const user = { id, username, room };
8
9 users.push(user);
10
11 return user;
12}
13
14
15
16// Get room users bascially we are filtering the user using roomname
17function getRoomUsers(room) {
18 return users.filter(user => user.room === room);
19}
20
21
22Listening the Events from client side
23socket.on("join_room",({username,room,time,userType})=>{
24 //getting the username,room,time and user type from client
25
26 //Pusing the user to the user array to join the room
27 const user = userJoin(socket.id,username,room);
28 socket.join(user.room);
29
30 //getting the roomUser from a particular room
31 const data = getRoomUsers(room);
32
33 //After getting the toom Users we are emiting to client side
34 io.to(user.room).emit("roomUsers",{
35 room:user.room,
36 users:getRoomUsers(user.room)
37 })
38
39
40 //we are emitting the userdata to room
41 const data ={
42 username:username,
43 room:room,
44 id:socket.id,
45 message:`${username} has joined the chat`,
46 time:time,
47 st:st
48 }
49
50 io.to(room).emit("new_user",data)
51
52
53
54})
55
Here we have handled the event in server side now after getting the request from client we are again sending back the response to to the client
Two event we have to listen on client side
Lets hanlde these two event in client side
Create a Chat.js file in components folder and paste the below code
1import React, { useEffect, useState } from "react";
2import ScrollToBottom from "react-scroll-to-bottom";
3const Chat = ({
4
5 usesrList,
6 sendMessage,
7 onChange,
8 message,
9 roomUsers,
10 id,
11}) => {
12
13
14
15
16 return (
17 <>
18 <div className="container">
19 <div className="form_group">
20 <div className="sidebar">
21 <div className="main_sidebar">
22 <div className="group_info">
23 <div className="grpmain">
24 <div className="grphead">
25 <h1>Group: {roomUsers.room}</h1>
26 </div>
27 <div className="grpcnt">
28 <div>
29 <p>😈Nothing will be Stored!!!😈</p>
30 </div>
31
32 <p>Acitve : 0</p>
33
34 </div>
35 </div>
36 <hr color="#0abeef" />
37 </div>
38
39 <div className="usersInfo">
40 <div className="usrmain">
41 <div className="usrhead">
42 <h4>Currently Online</h4>
43 </div>
44
45
46 </div>
47 </div>
48 </div>
49 </div>
50
51 <div className="main_content">
52 <div className="msgtitle">
53 <div className="fl">
54 <h1>WELCOME TO RANDOM CHAT ROOM</h1>
55 <div className="spanuser">
56 <span>Group : {roomUsers && roomUsers.room} </span>
57 </div>
58 </div>
59 </div>
60 <div className="main_message">
61 <div className="message_in">
62 <div className="show_messages">
63 <div className="messagecontainer">
64 <ScrollToBottom className="sp">
65 {usesrList &&
66 usesrList.map((user) => {
67 return (
68 <div
69 className="msgg "
70 id={id === user.id ? "your" : "othe"}
71 >
72 <div className="msgboxmain">
73 <div className="msgboxhead">
74 <p>{user.username}</p>
75 <p className="ptime">{user.time}</p>
76 </div>
77 <div className="msgboxcnt">
78 { user.message && (
79 <p>
80 {id === user.id && user.userType === "new_user"
81 ? "You have Joined The Chat"
82 : user.message}
83 </p>
84 )
85 }
86 </div>
87 </div>
88
89 </div>
90 );
91 })}
92 </ScrollToBottom>
93 </div>
94 </div>
95 <div className="btn">
96 <div className="msg_div">
97 <form
98 onSubmit={sendMessage}
99 id="form"
100 className="msgcntdiv"
101 >
102 <div className="input">
103 <textarea
104 className="sb"
105 spellcheck="false"
106 type="text"
107 message={message}
108 onChange={onChange}
109 />
110 </div>
111 </form>
112 </div>
113 </div>
114 </div>
115 </div>
116 </div>
117 </div>
118 </div>
119 </>
120 );
121};
122
123export default Chat;
124
1import "./App.css";
2import React, { useEffect, useState } from "react";
3import Main from "./assets/Components/Main";
4import Chat from "./assets/Components/Chat";
5
6const { io } = require("socket.io-client");
7
8const socket = io("http://localhost:8000");
9function App() {
10
11
12 const [username,setUsername] = useState("");
13 const [room,setRoomname] = useState("");
14
15 //checking if we are in MainPage or in chat Page
16 const [isMainPage,setIsMainPage] = useState(true);
17
18
19//storing the message
20 const [message,setMessage] = useState("");
21
22 // when Form is submited this function will be fired while joing the room
23 const onclick = (e) => {
24 const onclick = (e) => {
25 e.preventDefault();
26 // console.log(username);
27 setIsMainPage(false);
28 const data = {
29 username: username,
30 room: room,
31 id: socket.id,
32 time:
33 new Date(Date.now()).getHours() +
34 ":" +
35 new Date(Date.now()).getMinutes(),
36 st: "new_user",
37 };
38 socket.emit("join_room", data);
39 };
40
41 };
42
43 //store the current Users List
44 const [usesrList, setUserList] = useState([]);
45
46 //Sending the message we will handle it later
47 const sendMessage = async()=>{
48
49 }
50
51
52 //handle the incoming event from server side and update the Ui
53 useEffect(() => {
54 //getting the roomUsers eveent which we have emited frin server
55 socket.on("roomUsers", ({ users, room }) => {
56 const data = {
57 users: users,
58 room: room,
59 };
60 setRoomUsers(data);
61 });
62
63 //getting the newUsers details
64 socket.on("new_user", (data) => {
65 setUserList((list) => [...list, data]);
66
67 });
68 }, []);
69
70
71 return (
72 <>
73 <div className="conatiner">
74
75 {isMainPage?
76 <Main
77 onclick={onclick}
78 value={username}
79 username={username}
80 onroomchange={(e) => {
81 setRoomname(e.target.value);
82 }}
83 onuserchange={(e) => {
84 setUsername(e.target.value);
85 }}
86 room={room}
87 />
88
89 : <Chat
90
91 usesrList={usesrList}
92 message={message}
93 onChange={(e) => {
94 setMessage(e.target.value);
95 }}
96 id={socket.id}
97 sendMessage={sendMessage}
98 roomUsers={roomUsers}
99 />}
100
101
102 </div>
103 </>
104 );
105}
106
107export default App;
108
Now have successfully created Our Chat Page and handled the joined user
Our Chat Page Will look like thiis
Now handling the message Part
Update the sendMessage Function
1 const sendMessage = async()=>{
2 if( message!=="") {
3 e.preventDefault();
4 const messageData = {
5 room: room,
6 username: username,
7 message: message,
8 id: socket.id,
9 time:
10 new Date(Date.now()).getHours() +
11 ":" +
12 new Date(Date.now()).getMinutes(),
13 st: "message",
14 };
15 await socket.emit("send_message", messageData);
16 // setUserList((list)=>[...list,messageData]);
17
18 setMessage("");
19 e.preventDefault();
20
21
22 }
23 }
Lets handle send_message event in server side
Goto server.js and add the following code
1socket.on("send_message",(data)=>{
2 //we are receiving the message and again sending back to the specific room
3 io.to(data.room).emit("receive_message",data);
4})
5
Now lets handle the received message on Frontend
1useEffect(() => {
2 //basically we are storing all the data in userlist i.e username message socketid and soon(Just adding the message to previous list)
3 socket.on("receive_message", (data, e) => {
4 setUserList((list) => [...list, data]);
5
6 });
7
8 socket.on("roomUsers", ({ users, room }) => {
9 const data = {
10 users: users,
11 room: room,
12 };
13 setRoomUsers(data);
14 });
15 socket.on("new_user", (data) => {
16 setUserList((list) => [...list, data]);
17 const mes = `${data.message}`;
18 setJoinedMes(mes);
19
20 });
21 }, []);
22
Congratulation!! You have successfully Created your chat App
For more Info
Github repo: https://github.com/Technicalranjitofficial/Random-chat/tree/main
Building a chat application using Socket.IO, Node.js, and React has provided us with a hands-on experience in harnessing the power of real-time communication.
If you like this blog then share it with your friends.
© Copyright 2023 - Made with 💓 by Ranjit Das All right reserved