Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Nardin
Nardin

Posted on

     

Real-time notifications with React and Socket-IO

Lately I have been trying to implement a notification system for my React application using the socket.io library. I want to share what I learned about it and also my implementation.
This is a simple example. Let's begin :)

These are the things you can get to know from this article.

  1. Why do we need to use socket-io?
  2. What is socket-io?
  3. How to use socket-io in React and Node applications?
  4. Implementing a simple chatroom app

I want to implement a simple chat application where you can login just by entering your name and write a message and send it to every other user that is online in the application.

The question is, how can we get all messages in real-time without refreshing the page?
The first approach that may come to mind is to use the Rest API and send requests to fetch new messages every few minutes. This process is known as polling, and it is not really a good approach for scenarios like this. Why?
First, assume you have no new messages but send requests every minute to know if there are any. Second, you are not able to get a new message just in time, and it makes the user experience worse or less enjoyable.

Another approach and better one is somehow making the server send new messages without getting a request from the user. If we can do this, we don't need to send new requests every minute, and it has a better user experience. Here, socket-io can help us.

What is socket-io?

To answer this question first, you should know about WebSocket.

WebSocket

The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.

Socket.IO is a JavaScript library that provides a higher-level abstraction on WebSocket, making it easier and faster to develop real-time functionality compared to using raw WebSocket.

The main idea behind socket.io is that you can send and receive any events you want, with any data you want.
Here is a simple implementation of how to use socket-io in React in the front-end and express in the back-end.

front-end
Make sure you have React and socket.io-client installed on your machine. If not try these commands:

npx create-react-app my-app --template typescriptcd my-appnpm install socket.io-clientnpm start
Enter fullscreen modeExit fullscreen mode

In App component when a user set her username, inside 'loginHandler' function we create a connection to server using socket-io and user emit an event which is named 'hello-server'.
On the other side, the server will listen to this event and has its own callback function to occur whenever this event happens.
Here is the App component:

import{useState}from"react";import{io,Socket}from"socket.io-client";importLoginfrom"./Login";importMessageBoxfrom"./MessageBox";constWS_URL="http://localhost:5000";interfaceServerToClientEvents{"new-message":(message:string,username:string)=>void;}interfaceClientToServerEvents{"hello-server":(usernameInput:string)=>void;"send-message":(message:string,username:string)=>void;}exporttypeMySocket=Socket<ServerToClientEvents,ClientToServerEvents>;constApp=()=>{const[username,setUsername]=useState<string>("");const[socket,setSocket]=useState<MySocket>();constloginHandler=(usernameInput:string)=>{setUsername(usernameInput);constsocket:MySocket=io(WS_URL);setSocket(socket);socket.emit(`hello-server`,usernameInput);};return(<divclassName="w-full h-screen flex flex-col items-center overflow-scroll"><divclassName="p-2 bg-orange text-white m-2 rounded-2xl">{username===""?"Ofline":username}</div>{username===""?(<LoginonLogin={loginHandler}/>):(<MessageBoxsocket={socket!}username={username}/>)}</div>);};exportdefaultApp;
Enter fullscreen modeExit fullscreen mode

In the Login component, we simply enter our username and submit it.
./Login.tsx

import{useState}from"react";constLogin=({onLogin}:{onLogin:(usernameInput:string)=>void})=>{const[inputValue,setInputValue]=useState("");constsubmitHandler=()=>{if(inputValue==="")return;onLogin(inputValue);};return(<><labelclassName="p-4">PLease enter your username to login:</label><inputtype="text"value={inputValue}onChange={(e)=>setInputValue(e.target.value)}className="border-[0.1rem] border-gray-dark p-4"/><buttononClick={submitHandler}className="bg-gray-dark text-white py-2 px-4 m-4 hover:text-orange">        Login</button></>);};exportdefaultLogin;
Enter fullscreen modeExit fullscreen mode

When a user sends a new message, the socket tells the server that there is a new notification by emitting a "send-message" event, and all we need to do is listen to this event, just like the 'hello-server' event in the App component, and the server emits a new event in response to this event ("send-message" event), which is "new-message", and the client also listens to this event in the 'MessageBox' component.

./MessageBox.tsx

import{useEffect,useState}from"react";import{MySocket}from"./App";constMessageBox=({socket,username,}:{socket:MySocket;username:string;})=>{const[inputMessage,setInputMessage]=useState<string>("");const[messagesFromServer,setMessagesFromServer]=useState<string[]>([]);useEffect(()=>{socket.on("new-message",(message:string,username:string)=>{constnewMessage=`${username}:${message}`;setMessagesFromServer((pre)=>[newMessage,...pre]);});return()=>{socket.close();};},[socket]);constsendMessageHandler=(event:React.MouseEvent<HTMLButtonElement>)=>{event.preventDefault();if(inputMessage==="")return;socket.emit("send-message",inputMessage,username);setInputMessage("");};return(<><divclassName="w-full h-4/5 p-4 overflow-scroll"><divclassName="text-gray-dark font-bold py-4">Chat room</div>{messagesFromServer.map((message,index)=>(<divkey={index}className="bg-gray-dark text-white w-fit px-4 py-1 rounded-2xl my-2">{message}</div>))}</div><divclassName="fixed bottom-1 left-0 w-full flex flex-row justify-between px-4"><inputtype="text"value={inputMessage}onChange={(e)=>{setInputMessage(e.target.value);}}className="w-full border-[0.1rem] rounded-3xl outline-none p-4 border-gray-dark"/><buttononClick={sendMessageHandler}className="w-16 p-2 rounded-3xl  bg-gray-dark text-white hover:text-orange">          Send</button></div></>);};exportdefaultMessageBox;
Enter fullscreen modeExit fullscreen mode

back-end
In server side make sure you have node, socket-io and express installed on your machine. If not try this command:

npm install node express socket.io-client
Enter fullscreen modeExit fullscreen mode

Let's initialize a new instance of socket.io by passing the server (the HTTP server) object, listen on the 'connection' event for incoming sockets.
And also listen to the events that the client may emit, which are "hello-server" and "send-message".

importexpressfrom"express";import{createServer}from"http";import{Server,Socket}from"socket.io";interfaceServerToClientEvents{"new-message":(message:string,username:string)=>void;}interfaceClientToServerEvents{"hello-server":(usernameInput:string)=>void;"send-message":(message:string,username:string)=>void;}typeWSServer=Server<ClientToServerEvents,ServerToClientEvents>;typeWSSocket=Socket<ClientToServerEvents,ServerToClientEvents>;constapp=express();constserver=createServer(app);constws:WSServer=newServer(server,{cors:{origin:["http://localhost:3000","https://admin.socket.io"],},});ws.on("connection",(socket:WSSocket)=>{console.log("Connection established");socket.on("hello-server",(username:string)=>{console.log(`${username} say hello`);});socket.on("send-message",(message:string,username:string)=>{console.log(message);ws.emit("new-message",message,username);});});server.listen(5000);console.log("Listening on port 5000");
Enter fullscreen modeExit fullscreen mode

You can find the full app on my GitHub.
https://github.com/nardinsy/chatroom-socket-io-demo

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp