Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • Official Blog
  • Nearby Places Finder
  • Direction Route Finder
  • Distance & Time Calculator
Menu

React.js Flask Project to Build Socket.io Realtime Chat App in Browser Using JSX For Beginners

Posted on October 27, 2022

 

 

 

Welcome folks today in this blog post we will be building a realtime chat app in flask and react.js using the socket.io library. All the full source code of the application is shown below.

 

 

Get Started

 

 

In order to get started you need to create an empty directory called chatapp where you will create the react.js and flask app as shown below

 

 

cd chatapp

 

 

mkdir chatapp

 

 

Making the Flask Backend of the App

 

 

Now guys first of all we will be building the flask app the actual backend server for this project. Now here make a backend folder inside the root directory as shown below

 

 

mkdir backend

 

 

Now you need to install the dependencies for this project as shown below

 

Just make a requirements.txt file and copy paste the below dependencies as shown below

 

 

requirements.txt

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bidict==0.22.0
click==8.1.3
dnspython==2.2.1
eventlet==0.33.1
Flask==2.1.2
Flask-Cors==3.0.10
Flask-SocketIO==5.2.0
greenlet==1.1.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
python-engineio==4.3.2
python-socketio==5.6.0
six==1.16.0
Werkzeug==2.1.2

 

 

pip install -r requirements.txt

 

 

As you can see we have installed the below dependencies as shown below

 

 

flask

 

flask_cors

 

flask_socketio

 

 

As you can see we are installing the actual flask package and also for making the api accessible to all origin and preventing the cors error from happening we are installing the cors package for flask which is flask_cors and also the socket.io library for flask which is flask_socketio which is used for realtime communication between the client and the server.

 

 

Now you need to make an app.py file inside the backend directory and copy paste the below code

 

 

app.py

 

 

Python
1
2
3
from flask import Flask, request,jsonify
from flask_socketio import SocketIO,emit
from flask_cors import CORS

 

 

As you can see we are importing all the packages which will be needed for this application using the import statement. Here we are importing the flask request and jsonify module to actually make the request and send the response to client in json. And also we are importing the flask socket.io module and also the emit function which is used to emit events to the client. And lastly we are also importing the flask_cors middleware package as well to prevent the cors error.

 

 

Starting the Flask App on Port Number

 

 

Now guys in the next step we will be initialize a simple flask app and passing the required middlewares of cors and socket.io and then we will be starting the app at a particular port number as shown below

 

 

1
2
3
4
5
6
7
8
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
CORS(app,resources={r"/*":{"origins":"*"}})
socketio = SocketIO(app,cors_allowed_origins="*")
 
 
if __name__ == '__main__':
    socketio.run(app, debug=True,port=5001)

 

 

As you can see we are passing the cors middleware and inside that we are passing all origins using the * operator. And also we are wrapping our flask app inside the socketIO constructor to make it realtime app. And also inside it we are passing the cors middleware as the second argument. And also we are configuring a secret key to the flask app as well.

 

 

Making the HTTP Get Route

 

 

Now we will be writing the HTTP Get Route inside that we will be returning the simple json response as shown below

 

 

Python
1
2
3
4
5
@app.route("/http-call")
def http_call():
    """return JSON with string data as the value"""
    data = {'data':'This text was fetched using an HTTP call to server on render'}
    return jsonify(data)

 

 

Inside the above request we are making the simple get route which is called /http-call inside this we are simple returning a json object in which we are returning the data response and then we are converting the response to json using the jsonify() method.

 

 

Listening For Connect Event Using Socket.io Library

 

 

Python
1
2
3
4
5
6
@socketio.on("connect")
def connected():
    """event listener when client connects to the server"""
    print(request.sid)
    print("client has connected")
    emit("connect",{"data":f"id: {request.sid} is connected"})

 

Now we will be writing the code to connect with the socket.io library. Here in this code we are defining a simple socket.io event which is called as connect inside this event we are listening on for the client which will be connected this event will be fired automatically and here inside this event we are emitting a custom event using the emit() method. Here in this we are returning the socket id using the request.sid property.

 

 

Listening For Disconnect Event Using Socket.io Library

 

 

Python
1
2
3
4
5
@socketio.on("disconnect")
def disconnected():
    """event listener when client disconnects to the server"""
    print("user disconnected")
    emit("disconnect",f"user {request.sid} disconnected",broadcast=True)

 

 

Now we will be defining the code to listen for the disconnect event when the client will be disconnected then this event will be automatically fired and inside this event we will  broadcasting the event to all clients using the emit() method. We will be telling all the clients which are currently connected that this current client is disconnected and we are sending out the socket id to all the clients.

 

 

Listening For the Chat Message and Sending it to All Clients

 

 

Python
1
2
3
4
5
@socketio.on('data')
def handle_message(data):
    """event listener when client types a message"""
    print("data from the front end: ",str(data))
    emit("data",{'data':data,'id':request.sid},broadcast=True)

 

Now guys we will be listening for the data or custom chat message event. In this event we will be listening for the chat messages that will be sent from the socket or client id to the server side. And after that we are getting the chat message inside the argument and then we are broadcasting that chat message to all the clients using the emit() method. Inside this emit() method we are emitting out the custom event called data and in the second argument we are passing the object which contains the actual chat message and also the socket id as well and lastly we have the broadcast property set to true.

 

 

Full Flask Backend (app.py) Source Code

 

 

app.py

 

 

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from flask import Flask, request,jsonify
from flask_socketio import SocketIO,emit
from flask_cors import CORS
 
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
CORS(app,resources={r"/*":{"origins":"*"}})
socketio = SocketIO(app,cors_allowed_origins="*")
 
@app.route("/http-call")
def http_call():
    """return JSON with string data as the value"""
    data = {'data':'This text was fetched using an HTTP call to server on render'}
    return jsonify(data)
 
@socketio.on("connect")
def connected():
    """event listener when client connects to the server"""
    print(request.sid)
    print("client has connected")
    emit("connect",{"data":f"id: {request.sid} is connected"})
 
@socketio.on('data')
def handle_message(data):
    """event listener when client types a message"""
    print("data from the front end: ",str(data))
    emit("data",{'data':data,'id':request.sid},broadcast=True)
 
@socketio.on("disconnect")
def disconnected():
    """event listener when client disconnects to the server"""
    print("user disconnected")
    emit("disconnect",f"user {request.sid} disconnected",broadcast=True)
 
if __name__ == '__main__':
    socketio.run(app, debug=True,port=5001)

 

 

Making the React.js Frontend App

 

 

Now we will be making the react.js frontend project inside the root folder as shown below

 

 

mkdir frontend

 

 

cd frontend

 

 

npx create-react-app chatapp

 

 

cd chatapp

 

 

Now we will be installing the dependencies for this project as shown below

 

 

npm i socket.io

 

 

npm i socket.io-client

 

 

As you can see we are installing the above dependencies which are the socket.io clients for the react.js app. Now you can see the directory structure of the react.js app as shown below

 

 

 

Now you need to make the App.js file and copy paste the below code as shown below

 

 

App.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import HttpCall from "./components/HttpCall";
import WebSocketCall from "./components/WebSocketCall";
import { io } from "socket.io-client";
import { useEffect, useState } from "react";
 
function App() {
  const [socketInstance, setSocketInstance] = useState("");
  const [loading, setLoading] = useState(true);
  const [buttonStatus, setButtonStatus] = useState(false);
 
  const handleClick = () => {
    if (buttonStatus === false) {
      setButtonStatus(true);
    } else {
      setButtonStatus(false);
    }
  };
 
  useEffect(() => {
    if (buttonStatus === true) {
      const socket = io("localhost:5001/", {
        transports: ["websocket"],
        cors: {
          origin: "http://localhost:3000/",
        },
      });
 
      setSocketInstance(socket);
 
      socket.on("connect", (data) => {
        console.log(data);
      });
 
      setLoading(false);
 
      socket.on("disconnect", (data) => {
        console.log(data);
      });
 
      return function cleanup() {
        socket.disconnect();
      };
    }
  }, [buttonStatus]);
 
  return (
    <div className="App">
      <h1>React/Flask App + socket.io</h1>
      <div className="line">
        <HttpCall />
      </div>
      {!buttonStatus ? (
        <button onClick={handleClick}>turn chat on</button>
      ) : (
        <>
          <button onClick={handleClick}>turn chat off</button>
          <div className="line">
            {!loading && <WebSocketCall socket={socketInstance} />}
          </div>
        </>
      )}
    </div>
  );
}
 
export default App;

 

 

Code Explanation

 

 

As you can see in the above code we are first of all importing the hooks which are useState and useState and also we are importing the socket.io client from that we are importing the io method.

 

 

JavaScript
1
2
import { io } from "socket.io-client";
import { useEffect, useState } from "react";

 

 

And then we are declaring three state variables using the useState hook which are socket,buttonStatus and loading variable as shown below

 

 

JavaScript
1
2
3
const [socketInstance, setSocketInstance] = useState("");
const [loading, setLoading] = useState(true);
const [buttonStatus, setButtonStatus] = useState(false);

 

 

Now we will be having the button to toggle the chat message box using the state variable called buttonStatus. And also we are displaying the HttpCall component to render the data from the server side using the http get request. And then we have a different component called WebSocketCall and inside this component we are passing the socket variable

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div className="App">
      <h1>React/Flask App + socket.io</h1>
      <div className="line">
        <HttpCall />
      </div>
      {!buttonStatus ? (
        <button onClick={handleClick}>turn chat on</button>
      ) : (
        <>
          <button onClick={handleClick}>turn chat off</button>
          <div className="line">
            {!loading && <WebSocketCall socket={socketInstance} />}
          </div>
        </>
      )}
    </div>

 

 

And also inside the useEffect hook when we load the application for the very first time we are first of all checking the buttonStatus to true inside that we are initializing a new socket reference inside that we are connecting to the flask web server url which is localhost:5001. And also we are also passing the cors origin url which is localhost:3000. And after that we are setting the socketInstance to this variable. And then we are listening for the different events such as connect,disconnect and the chat message data event.

 

 

 

 

 

 

 

Making the Components

 

 

Now we will be making the components folder inside that we will be making the HttpCall.jsx file and copy paste the following code

 

 

components/HttpCall.jsx

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { useEffect, useState } from "react";
 
export default function HttpCall() {
  const [data, setData] = useState("");
 
  useEffect(() => {
    fetch("/http-call", {
      headers: {
        "Content-Type": "application/json",
      },
    })
      .then((response) => response.json())
      .then((responseData) => {
        setData(responseData.data);
      });
  });
  return (
    <>
      <h2>HTTP Communication</h2>
      <h3 className="http">{data}</h3>
    </>
  );
}

 

 

As you can see we are importing the useState and useEffect hooks at the top and inside that we are calling the http get method to the backend url /http-status to render the simple json message inside the browser. And in the headers we are setting the content-type to application/json and then we are converting the response to json using json() method and then we are displaying the data using the setData() method using useState hook.

 

 

Now we will be making the second component which is called WebSocketCall.jsx file which is responsible for making the chat input field to send and display messages from the backend flask server.

 

 

components/WebSocketCall.jsx

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { useEffect, useState } from "react";
 
export default function WebSocketCall({ socket }) {
  const [message, setMessage] = useState("");
  const [messages, setMessages] = useState([]);
 
  const handleText = (e) => {
    const inputMessage = e.target.value;
    setMessage(inputMessage);
  };
 
  const handleSubmit = () => {
    if (!message) {
      return;
    }
    socket.emit("data", message);
    setMessage("");
  };
 
  useEffect(() => {
    socket.on("data", (data) => {
      setMessages([...messages, data.data]);
    });
    return () => {
      socket.off("data", () => {
        console.log("data event was removed");
      });
    };
  }, [socket, messages]);
 
  return (
    <div>
      <h2>WebSocket Communication</h2>
      <input type="text" value={message} onChange={handleText} />
      <button onClick={handleSubmit}>submit</button>
      <ul>
        {messages.map((message, ind) => {
          return <li key={ind}>{message}</li>;
        })}
      </ul>
    </div>
  );
}

 

 

 

 

 

As you can see inside this component we have the simple input field and then we have the submit button to send the message to the server. Here first of all when someone enters the message and when we click the submit button we will emitting the data event to the server and then the server broadcasts that event or chat message to all the connected clients using socket.io. In the above screenshot we have multiple clients connected so whenever you send message from one browser tab or one client when we type the message we broadcast it to all the clients connected as shown above.

 

And lastly we are using the map() method inside the jsx to loop through all the messages and display it using the <li> tags. And in useEffect() hook we are fetching all the messages using the socket.io event

 

Recent Posts

  • Android Java Project to Crop,Scale & Rotate Images Selected From Gallery and Save it inside SD Card
  • Android Kotlin Project to Load Image From URL into ImageView Widget
  • Android Java Project to Make HTTP Call to JSONPlaceholder API and Display Data in RecyclerView Using GSON & Volley Library
  • Android Java Project to Download Youtube Video Thumbnail From URL & Save it inside SD Card
  • Android Java Project to Embed Google Maps & Add Markers Using Maps SDK
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme