Sending and receiving text messages in recent times are frequently done online and in real-time. Text messages in real-time chat applications are sent and received immediately, depending on the speed of the router. Realtime messaging is very essential in chat applications, and Socket.io grants us this privilege.
In this tutorial, you’ll build a chat application hovering around:
To follow effectively with this tutorial, be sure you have:
This article is a modification of How to Build a Real-time Chat Forum using Strapi, Socket.io, React, and MongoDB.
Now that all is correct, let’s set up the PostgreSQL database.
Search and open up PgAdmin in the start menu of your computer. PgAdmin will help create and manage your Strapi database.
PgAdmin is installed when you install PostgreSQL.
- When PgAdmin opens, you will be prompted to put in the password entered during the installation.
The name of the database, chatapp, will be shown on the left navigation bar as shown below:
In this last section, you learned how to create a database in PostgreSQL. In this section, you’ll learn how to connect PostgreSQL with Strapi using the Quickstart option and the Custom setup option.
Open up your terminal and create a folder for this application. This folder is the project’s root directory for this application. In this tutorial, the name of this folder is strapified-chat. Not a bad name, right?
1 mkdir strapified-chat
Open the folder in your desired code editor or run the code below in your terminal to open the folder with Vs code:
cd strapified-chat
code .
After starting your code editor, open the integrated terminal in your code editor to quickly initialize and create a package.json file for the project using the code below:
npm init --y
Now, run the command below to create the Strapi app. You can give the Strapi app the name you desire but, in this tutorial, the name of the strapi app is chatapp.
npx create-strapi-app chatapp
Executing the create-strapi-app
command will bring you to an option shown below:
Use your down arrow key to select Custom and hit Enter
. Selecting Custom allows you to choose the database you want and a few other settings. Navigate using your arrow keys, select postgres, and hit Enter
:
Since the Strapi app and database have the same name, chatapp, just hit Enter
to move on.
If
chatapp
is not the name of your PostgreSQL database, specify the name of the database and hitEnter
.
Press Enter
to leave Host and Port as default. Key in postgres
as the Username. postgres
is the default name assigned when creating the database.
Enter the password to your database:
Enter n
to disable SSL connection.
Once the series of questions are over, Strapi creates the project with the custom options you specified. When the installation is done, Strapi sends a success message and outlines the basic commands that help get your project started.
Now that you have installed Strapi into the application, it’s time to get access to Strapi admin. Move into the created project and run the strapi build command
below to build the Strapi admin UI:
cd chatapp
npm run build
The output is shown below:
Now, run the strapi develop command
below to start up Strapi in development mode:
npm run develop
If the above step worked for you, kindly skip to the next section or stick around to gain more knowledge.
create-strapi-app
command below. This will create a Strapi app named chatapp
: npx create-strapi-app chatapp --quickstart
The quickstart option automatically builds the admin panel and runs Strapi in development mode.
1 module.exports = ({ env }) => ({
2 connection: {
3 client: "postgres",
4 connection: {
5 host: env("DATABASE_HOST", "127.0.0.1"),
6 port: env.int("DATABASE_PORT", 5432),
7 database: env("DATABASE_NAME", "chatapp"),//Name of database
8 user: env("DATABASE_USERNAME", "postgres"),//Default username
9 password: env("DATABASE_PASSWORD", "12345678"),//Password to your PostgreSQL database
10 ssl: env.bool("DATABASE_SSL", false),
11 },
12 },
13 });
Once you’re done inputing the code above in your database.js file, hit save and let Strapi restart the server.
After connecting PostgreSQL with Strapi, the next step is to install NextJS into the Chat application.
create-next
app command below to move out from the Strapi folder and spin up the next application in a new folder. cd ..
npx create-next-app next-chat
Nodemailer is a NodeJS module that enables you to send emails from your email server. Nodemailer makes use of the credential of your email service to send these emails. In this section, you will learn how to set up Nodemailer for your different email services. Now, open your terminal in the next-chat directory and install nodemailer.
cd next-chat
npm i nodemailer
Below is the output of the installation of nodemailer:
Once the installation of Nodemailer is complete, navigate to pages/api in the next-chat project directory and create a file named mail.js.
To send an email using nodemailer requires an email service. This tutorial makes use of the Google Mail service (Gmail), but you can choose a different email or SMTP service.
To make use of the Google Mailing Service with nodemailer, you need to allow access to a less secured app.
1 export default function (req, res) {
2 const nodemailer = require("nodemailer");
3 const transporter = nodemailer.createTransport({
4 port: 465,
5 host: "smtp.gmail.com",
6 secure: "true",
7 auth: {
8 user: "examaple@gmail.com",//Replace with your email address
9 pass: "example",// Replace with the password to your email.
10 },
11 });
12 const mailData = {
13 from: "Chat API",
14 to: req.body.email,
15 subject: `Verify your email`,
16 text: req.body.message,
17 };
18 transporter.sendMail(mailData, function (err, info) {
19 if (err)
20 return res.status(500).json({ message: `an error occurred ${err}` });
21 res.status(200).json({ message: info }); de
22 });
23 }
Now that nodemailer has been configured, let's create a simple login form that will accept the email from the user.
1 import styles from "../styles/Home.module.css";
2 export default function Home() {
3 return (
4 <div className={styles.container}>
5 <form className={styles.main}>
6 <h1>Login</h1>
7 <label htmlFor="name">Email: </label>
8 <input type="email" id="name" />
9 <br />
10 <input type="submit" />
11 </form>
12 </div>
13 );
14 }
After refactoring the index.js file and creating a simple form, the next step is to add functionality.
1 export default function Home() {
2 const [email, setEmail] = useState("");
3 const [user, setUser] = useState("");
4 return (
5 <div className={styles.container}>
6 <form className={styles.main}>
7 <h1>Login</h1>
8 <label htmlFor="user">Username: </label>
9 <input
10 type="text"
11 id="user"
12 value={user}
13 onChange={(e) => setUser(e.target.value)} // Getting the inputs
14 />
15 <br />
16 <label htmlFor="name">Email: </label>
17 <input
18 type="email"
19 id="name"
20 onChange={(e) => setEmail(e.target.value)} // Getting the inputs
21 />
22 <br />
23 <input type="submit" />
24 </form>
25 </div>
26 );
27 }
api/mail
.1 export default function Home() {
2 const [email, setEmail] = useState("");
3 const [user, setUser] = useState("");
4 const handlesubmit = (e) => {
5 e.preventDefault();
6 let message = "Testing, Testing..... It works🙂";
7 let data = {
8 email, // User's email
9 message,
10 };
11 fetch("/api/mail", {
12 method: "POST", // POST request to /api//mail
13 headers: {
14 "Content-Type": "application/json",
15 },
16 body: JSON.stringify(data),
17 }).then(async (res) => {
18 if (res.status === 200) {
19 console.log(await res.json());
20 } else {
21 console.log(await res.json());
22 }
23 });
24 setEmail("");
25 setUser("");
26 };
27 return (
28 <div className={styles.container}>
29 <form className={styles.main}>
30 <h1>Login</h1>
31 <label htmlFor="user">Username: </label>
32 <input
33 type="text"
34 id="user"
35 value={user}
36 onChange={(e) => setUser(e.target.value)} // Getting the inputs
37 />{" "}
38 <br />
39 <label htmlFor="name">Email: </label>
40 <input
41 type="email"
42 id="name"
43 value={email}
44 onChange={(e) => setEmail(e.target.value)} // Getting the inputs
45 />
46 <br />
47 <input type="submit" onClick={handlesubmit} /> // Handling Submit
48 </form>
49 </div>
50 );
51 }
Once you are done with adding the code above and hitting save, head on to localhost:3000 to try out the form.
According to the documentation, JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. JWT generates a unique token that can authenticate and authorize a user.
npm i jsonwebtoken
The output is shown below.
2. Add the following code to the handsubmit
function in the index.js file.
1 const handlesubmit = (e) => {
2 e.preventDefault();
3 const id = Math.trunc(Math.random() * 1000000); //Generating a random number and taking the first 10 numbers.
4 let account = { // Creating the payload
5 id
6 };
7 const SECRET = "this is a secret"; //JWT secret
8 const token = jwt.sign(account, SECRET);// Creates the Token
9 console.log(token);
10 };
For security purposes, the
SECRET
variable for JWT should be a random set of strings and should be stored in an environmental variable.
Strapi is an open-source headless CMS that gives developers the freedom to choose their favorite tools and frameworks and allows editors to manage and distribute their content using their application's admin panel. Now that you’ve generated the token using JWT, it’s time to store the username, email, and token using my favorite CMS, Strapi.
cd chatapp
npm run develop
Navigate to localhost:1337/admin and log in with your Strapi admin credentials.
After a successful login, click on Content-Type Builder on the side-nav bar and click on Create new collection type*.*
Give it a name of your choice, but in this tutorial, the name of the collection type is Account.
After naming the collection type, hit continue, choose Text, and name it username.
Click on Add another field to configure the field for email and token. Choose the Email field for Email and Text field for Token, then hit finish. The output is shown below
Click on Save at the top-right of the screen and let Strapi restart the server.
To increase security, Strapi blocks all CRUD requests to a newly-created collection type by default. The user’s credential needs to be sent to the Account collection type, so this feature will not be needed in this application.
To allow requests, click on Settings on the side-nav bar and click on Roles under USERS & PERMISSIONS PLUGIN.
Scroll down to Accounts, click on the drop-down, Select all and hit Save at the top-right of the screen.
Now that you’ve learned how to edit the permission of a collection type, it’s time you learn how to store the user’s details in that collection type using Strapi.
cd next-chat
npm run dev
Open your index.js file in the pages folder and add the following code to the handlesubmit
function.
1 const handlesubmit = (e) => {
2 e.preventDefault();
3 let message = "Testing, Testing..... It works🙂";
4 const id = Math.trunc(Math.random() * 1000000); //Generating a random number and taking the first 10 numbers.
5 let data = {
6 email, // User's email
7 message,
8 };
9 let account = {
10 id
11 };
12 const SECRET = "this is a secret";
13 const token = jwt.sign(account, SECRET);
14 let strapiData = { // Parameters for Strapi
15 data: {
16 id,
17 username: user,
18 email,
19 token,
20 },
21 };
22 fetch("http://localhost:1337/api/accounts", {
23 method: "POST",
24 headers: {
25 "Content-type": "application/json",
26 },
27 body: JSON.stringify(strapiData), // Adding the parameters to the body.
28 }).then(async (res) => {
29 console.log(await res.json()); // Outputs the result
30 });
31
32 // The Rest of the code
33 };
Load up localhost:3000 in your favorite browser to test the request.
Fill in the Username and the Email then hit submit. Open up your in-browser console to confirm that it was successfully added.
Click on Content Manager in your Strapi’s admin panel to check if it was added to Strapi.
After setting up Strapi, the next step is to use the token stored in strapi to authenticate the user. To do this, a link containing the token will be sent to the user’s email.
handlesubmit
function.1 const handlesubmit = (e) => {
2 e.preventDefault();
3 const id = Math.trunc(Math.random() * 1000000); //Generating a random number and taking the first 10 numbers.
4 console.log(id);
5 let account = { // JWT payload
6 id,
7 };
8 const SECRET = "this is a secret";
9 const token = jwt.sign(account, SECRET);
10 let message = `http://localhost:3000/chat/${token}`; // Adding the token to the message sent to the user.
11 let data = {
12 email, // User's email
13 message,
14 };
15 fetch("/api/mail", {
16 method: "POST", // POST request to /api//mail
17 headers: {
18 "Content-Type": "application/json",
19 },
20 body: JSON.stringify(data),
21 }).then(async (res) => {
22 if (res.status === 200) {
23 console.log(await res.json());
24 } else {
25 console.log(await res.json());
26 }
27 });
28 setEmail("");
29 setUser("");
30 };
Once the link has been sent to the user and the user clicks on it, we need to get the token and verify it. This will prevent the user from generating random strings and in turn, it increases security.
Create a folder in the pages folder called chat and create a file in the chat folder named token.js
Add the following code to the token.js file to get the token from the URL and verify it using the JWT SECRET.
1 import { useRouter } from "next/router";
2 import { useEffect, useState } from "react";
3 import jwt from "jsonwebtoken";
4 export default function Chat() {
5 const router = useRouter();
6 const SECRET = "this is a secret"; // JWT Secret
7 const [done, setDone] = useState("");
8 const token = router.query.token; // Getting the token from the URL
9 useEffect(() => {
10 if (!router.isReady) return console.log("Loading... Please wait"); // Checking if the token has been fetched from the URL.
11 try {
12 const data = jwt.verify(token, SECRET); // Verifying the token using the secret
13 console.log(data); // Logging out the Payload.
14 setDone("done"); // Granting access to the chat page
15 } catch (error) {
16 router.push("/"); // Redirecting the user to the home page if an error occured
17 }
18 }, [token]); // Listens for a change in token
19 return (
20 <div>
21 {done !== "done" ? ( // Waiting for access to be granted
22 <h1>Verifying token..... Please wait</h1>
23 ) : (
24 <h1> Group Chat</h1>
25 )}
26 </div>
27 );
28 }
1 export default function Chat() {
2 // Rest of the code
3 useEffect(() => {
4 //Rest of the code
5 try {
6 const payload = jwt.verify(token, SECRET); // Verifying the token using the secret
7 async function fetchData() {
8 const data = await fetch(
9 `http://localhost:1337/api/accounts/${payload.id}`
10 );
11 const account = await data.json(); // Getting the user's data
12 console.log(account);
13 }
14 fetchData();
15 setDone("done"); // granting access to the chat page
16 } catch (error) {
17 router.push("/"); // redirecting the user to the home page if an error occured
18 }
19 }, [token]); // Listens for a change in token
20 // Rest of the code
21 }
1 // Rest of code
2
3 useEffect(() => {
4 // Rest of the code.
5
6 async function fetchData() {
7 const data = await fetch(
8 `http://localhost:1337/api/accounts/${payload.id}`
9 );
10 const account = await data.json();
11 if (token !== account.data.attributes.token) return router.push("/"); // Verifying if the user exist in Strapi
12 return;
13 }
14 fetchData();
15 // Rest of the code
16 }, [token])
17
18 // Rest of the code
Now that security has been added to the chat application, it’s time to set up our chat environment.
This article is a modification of a previous article. Refer to it for clarity on the various features.
Clone, fork or download the starter-ui file for this chat application using this GitHub link.
npm install
to install all the dependencies for this chat application. Once the installation is complete, run npm run dev
to start up the chat application.Please ensure that you add the right Gmail credentials to the mail.js file. Also, ensure your strapi server is running. To do this, open your terminal and run
npm run develop
in your strapi’s project folder.
After starting up the chat application, the next step is to add chat functionality to the application.
Create a new collection named message in Content-Type Builder and add 2 fields, a user field and a message field.
1 "use strict";
2 module.exports = {
3 /**
4 * An asynchronous register function that runs before
5 * your application is initialized.
6 *
7 * This gives you an opportunity to extend code.
8 */
9 register({ strapi }) {},
10 /**
11 * An asynchronous bootstrap function that runs before
12 * your application gets started.
13 *
14 * This gives you an opportunity to set up your data model,
15 * run jobs, or perform some special logic.
16 */
17 bootstrap(/* { strapi } */) {
18 //strapi.server.httpServer is the new update for Strapi V4
19 var io = require("socket.io")(strapi.server.httpServer, {
20 cors: { // cors setup
21 origin: "http://localhost:3000",
22 methods: ["GET", "POST"],
23 allowedHeaders: ["my-custom-header"],
24 credentials: true,
25 },
26 });
27 io.on("connection", function (socket) { //Listening for a connection from the frontend
28 socket.on("join", ({ username }) => { // Listening for a join connection
29 console.log("user connected");
30 console.log("username is ", username);
31 if (username) {
32 socket.join("group"); // Adding the user to the group
33 socket.emit("welcome", { // Sending a welcome message to the User
34 user: "bot",
35 text: `${username}, Welcome to the group chat`,
36 userData: username,
37 });
38 } else {
39 console.log("An error occurred");
40 }
41 });
42 socket.on("sendMessage", async (data) => { // Listening for a sendMessage connection
43 let strapiData = { // Generating the message data to be stored in Strapi
44 data: {
45 user: data.user,
46 message: data.message,
47 },
48 };
49 var axios = require("axios");
50 await axios
51 .post("http://localhost:1337/api/messages", strapiData)//Storing the messages in Strapi
52 .then((e) => {
53 socket.broadcast.to("group").emit("message", {//Sending the message to the group
54 user: data.username,
55 text: data.message,
56 });
57 })
58 .catch((e) => console.log("error", e.message));
59 });
60 });
61 },
62 };
1 import React, { useEffect, useState } from "react";
2 import { Input } from "antd";
3 import "antd/dist/antd.css";
4 import "font-awesome/css/font-awesome.min.css";
5 import Header from "./Header";
6 import Messages from "./Messages";
7 import List from "./List";
8 import socket from "socket.io-client";
9 import {
10 ChatContainer,
11 StyledContainer,
12 ChatBox,
13 StyledButton,
14 SendIcon,
15 } from "../pages/chat/styles";
16 function ChatRoom({ username, id }) {
17 const [messages, setMessages] = useState([]);
18 const [message, setMessage] = useState("");
19 const [users, setUsers] = useState([]);
20 const io = socket("http://localhost:1337");//Connecting to Socket.io backend
21 let welcome;
22 useEffect(() => {
23 io.emit("join", { username }, (error) => { //Sending the username to the backend as the user connects.
24 if (error) return alert(error);
25 });
26 io.on("welcome", async (data, error) => {//Getting the welcome message from the backend
27 let welcomeMessage = {
28 user: data.user,
29 message: data.text,
30 };
31 welcome = welcomeMessage;
32 setMessages([welcomeMessage]);//Storing the Welcome Message
33 await fetch("http://localhost:1337/api/messages")//Fetching all messages from Strapi
34 .then(async (res) => {
35 const response = await res.json();
36 let arr = [welcome];
37 response.data.map((one, i) => {
38 arr = [...arr, one.attributes];
39 setMessages((msgs) => arr);// Storing all Messages in a state variable
40 });
41 })
42 .catch((e) => console.log(e.message));
43 });
44 io.on("message", async (data, error) => {//Listening for a message connection
45 await fetch("http://localhost:1337/api/messages")
46 .then(async (res) => {
47 const response = await res.json();
48 let arr = [welcome];
49 response.data.map((one, i) => {
50 arr = [...arr, one.attributes];
51 setMessages((msgs) => arr);
52 });
53 })
54 .catch((e) => console.log(e.message));
55 });
56 }, [username]);
57 const sendMessage = (message) => {
58 if (message) {
59 io.emit("sendMessage", { message, user: username }, (error) => {// Sending the message to the backend
60 if (error) {
61 alert(error);
62 }
63 });
64 setMessage("");
65 } else {
66 alert("Message can't be empty");
67 }
68 };
69 const handleChange = (e) => {
70 setMessage(e.target.value);
71 };
72 const handleClick = () => {
73 sendMessage(message);
74 };
75 return (
76 <ChatContainer>
77 <Header room="Group Chat" />
78 <StyledContainer>
79 <List users={users} id={id} usersname={username}>
80 <ChatBox>
81 <Messages messages={messages} username={username} />
82 <Input
83 type="text"
84 placeholder="Type your message"
85 value={message}
86 onChange={handleChange}
87 />
88 <StyledButton onClick={handleClick}>
89 <SendIcon>
90 <i className="fa fa-paper-plane" />
91 </SendIcon>
92 </StyledButton>
93 </ChatBox>
94 </StyledContainer>
95 </ChatContainer>
96 );
97 }
98 export default ChatRoom;
1 import React, { useEffect, useRef } from "react";
2 import Message from "./Message/";
3 import styled from "styled-components";
4 function Messages(props) {
5 const { messages, username: user } = props;
6 const messagesEndRef = useRef(null);
7 const scrollToBottom = () => {
8 messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });//Scroll to bottom functionality.
9 };
10 useEffect(() => {
11 scrollToBottom();
12 }, [messages]);
13 return (
14 <StyledMessages>
15 {messages.map((message, i) => (
16 <div key={i} ref={messagesEndRef}>
17 <Message message={message} username={user} />
18 </div>
19 ))}
20 </StyledMessages>
21 );
22 }
23 export default Messages;
24 const StyledMessages = styled.div`
25 padding: 5% 0;
26 overflow: auto;
27 flex: auto;
28 `;
Lastly, add the following code to the index.js file in next-chat/components/Messages/Message. This code will neatly format the messages and position the messages in their rightful place.
import React from "react";
import { MessagesContainer, MessageBox, MessageText, SentBy } from "./styles";
function Message(props) {
const {
username,
message: { user, message },
} = props;
let sentByCurrentUser = false;
if (user === username) {
sentByCurrentUser = true;
}
const background = sentByCurrentUser ? "blue" : "dark";
const textPosition = sentByCurrentUser ? "end" : "start";
const textColor = sentByCurrentUser ? "white" : "dark";
const sentBy = sentByCurrentUser ? "right" : "left";
return (
The previous section covered how to set up socket.io for both the client and server sides of the application. This section will cover how to implement role-based auth in the chat application.
Create an active user collection type in Strapi, add a users field and socketid field, make sure it is set to a unique field and configure the roles permission.
Add the following code to the index.js file in chat-app/src to make a POST and request to the active users collection type.
1 // The rest of Code
2 socket.on("join", ({ username }) => {
3 console.log("user connected");
4 console.log("username is ", username);
5 if (username) {
6 socket.join("group");
7 socket.emit("welcome", {
8 user: "bot",
9 text: `${username}, Welcome to the group chat`,
10 userData: username,
11 });
12 let strapiData = {
13 data: {
14 users: username,
15 },
16 }
17 await axios
18 .post("http://localhost:1337/api/active-users", strapiData)//Storing the active users
19 .then(async (e) => {
20 socket.emit("roomData", { done: "true" });
21 })
22 .catch((e) => {
23 if (e.message == "Request failed with status code 400") {//Checking if user exists
24 socket.emit("roomData", { done: "existing" });
25 }
26 })
27
28 } else {
29 console.log("e no work");
30 }
31 });
32 //The rest of the code
1 //The rest of the code
2 useEffect(() => {
3 //The rest of the code
4
5 io.on("roomData", async (data) => {
6 await fetch("http://localhost:1337/api/active-users").then(async (e) => {
7 setUsers(await e.json());//Fetching and storing the users in the users state variable
8 });
9 //The rest of the code
10 }, [username]);
11
12 //The rest of the code
1 import React from "react";
2 import styled from "styled-components";
3 import { List as AntdList, Avatar } from "antd";
4 function List(props) {
5 const users = props.users.data;//Getting the users
6 return (
7 <StyledList>
8 <ListHeading>Active Users</ListHeading>
9 <AntdList
10 itemLayout="horizontal"
11 dataSource={users}
12 renderItem={(user) => (
13 <AntdList.Item>
14 <AntdList.Item.Meta
15 avatar={
16 <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
17 }
18 title={user.attributes.users}//Displaying the users
19 />
20 <button
21 style={
22 user.attributes.users === "Admin" || props.username !== "Admin"
23 ? { display: "none" }
24 : null
25 }//Verifying that the user is an Admin
26 >
27 Delete
28 </button>
29 </AntdList.Item>
30 )}
31 />
32 </StyledList>
33 );
34 }
35 export default List;
36 const StyledList = styled(AntdList)`
37 margin-right: 10px;
38 flex: 0 0 35%;
39 padding: 20px;
40 .ant-list-item-meta-content {
41 flex-grow: 0;
42 }
43 h4 {
44 font-size: 25px;
45 }
46 a {
47 color: #097ef0;
48 }
49 `;
50 const ListHeading = styled.div`
51 color: #757591;
52 font-size: 20px;
53 font-style: oblique;
54 border-bottom: 1px solid #757591;
55 `;
Populate the Account collection type with Admin as username. Head on to http://localhost:3000 to do so.
Click on Content-Type Builder in your Strapi’s admin dashboard and edit the username filed to take in unique sets of usernames for the Account collection type.
This delete function is a feature made accessible to only the Admin user.
It’s time to configure the delete function.
1 //The rest of the code
2 bootstrap(/* { strapi } */) {
3 //The rest of the code
4 io.on("connection", function (socket) {
5 // The rest of the code
6 socket.on("kick", (data) => {//Listening for a kick event
7 io.sockets.sockets.forEach((socket) => {
8 if (socket.id === data.socketid) {
9 socket.disconnect();//Disconnecting the User
10 socket.removeAllListeners();
11 return console.log("kicked", socket.id, data.socketid);
12 } else {
13 console.log("Couldn't kick", socket.id, data.socketid);
14 }
15 });
16 });
17 });
18 },
19 };
1 import React from "react";
2 import styled from "styled-components";
3 import { List as AntdList, Avatar } from "antd";
4 import socket from "socket.io-client";
5 function List(props) {
6 const users = props.users.data;
7 const handleClick = async (id, socketid) => {
8 const io = socket("http://localhost:1337");
9 await fetch("http://localhost:1337/api/active-users/" + id, {//Gets the id and delete the user from the active users collection.
10 method: "Delete",
11 headers: {
12 "Content-type": "application/json",
13 },
14 })
15 .then(async (e) => {
16 io.emit("kick", { socketid }, (error) => {//When the
17 if (error) return alert(error);
18 });
19 setTimeout(() => location.reload(), 3000);//Refreshes the page
20 })
21 .catch((e) => location.reload());//Refreshes the page if an error occured
22 };
23 return (
24 <StyledList>
25 <ListHeading>Active Users</ListHeading>
26 <AntdList
27 itemLayout="horizontal"
28 dataSource={users}
29 renderItem={(user) => (
30 <AntdList.Item>
31 <AntdList.Item.Meta
32 avatar={
33 <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
34 }
35 title={user.attributes.users}
36 />
37 <button
38 style={
39 user.attributes.users === "Admin" || props.username !== "Admin"
40 ? { display: "none" }
41 : null
42 }
43 onClick={() => handleClick(user.id, user.attributes.socketid)}//Passing the socketid as parameter to the handleClick function
44 >
45 Delete
46 </button>
47 </AntdList.Item>
48 )}
49 />
50 </StyledList>
51 );
52 }
53 export default List;
54 //The rest of the code
This article primarily aimed at teaching you how to set up different authenticating techniques in your application as well as enlightening you on how to utilize Strapi version 4.
Feel free to clone or fork the final code from the GitHub repo. As a next step, try to use this knowledge gained to build more complex applications using Strapi.
Full Stack Web Developer. Loves JavaScript.