I want to share a simple chat application that I've made using next js and socket-io.
To achieve this I've used Next.js and Socket.IO.
Next.js is a framework that most notably allows us to write server-rendered React apps easily.
Socket.IO is a JavaScript library for realtime web applications. It enables realtime, bi-directional communication between web clients and servers.
Front part
First step : creating the next application.
The command : npx create-next-app (we choose the name of app )
In next js we just need to add a file in pages folder to have all the routing stuff ....
We modify the existing file index.js.
firstly we import the necessary libraries
import React, { useState, useEffect } from "react"; | |
import socketIOClient from "socket.io-client"; | |
import userGen from "username-generator" | |
import { Button, Input } from 'reactstrap'; | |
const ENDPOINT = "http://127.0.0.1:4001"; | |
const socket = socketIOClient(ENDPOINT); |
In this work I've used functional components, much easier and more fun than class components, so we create the App component, we define some states that we need later.
1) a state to save the connected user list.
2) a state to save the message that we send.
3) a state to save the received messages.
After that we create the basic functions for communication between clients and server.
For each new client do :
1) in a useEffect hook we emit a login event to the server.
2) the server says:"Hi", and he sends the list of logged clients and also returns some information of the logged client such as socket_id.
End
Every client can send messages to all the users by emitting sendMsg event.
function App() { | |
const [user, setUser] = useState({ | |
usersList: null | |
}); | |
const [msg, setMsg] = useState(""); | |
const [recMsg, setRecMsg] = useState({ | |
listMsg: [] | |
}); | |
const [loggedUser, setLoggedUser] = useState(); | |
useEffect(() => { | |
// subscribe a new user | |
socket.emit("login", userGen.generateUsername()); | |
// list of connected users | |
socket.on("users", data => { | |
setUser({ usersList: JSON.parse(data) }) | |
}); | |
// get the logged user | |
socket.on("connecteduser", data => { | |
setLoggedUser(JSON.parse(data)); | |
}); | |
// we get the messages | |
socket.on("getMsg", data => { | |
let listMessages = recMsg.listMsg; | |
listMessages.push(JSON.parse(data)); | |
setRecMsg({ listMsg: listMessages }); | |
}); | |
}, []); | |
// to send a message | |
const sendMessage = () => { | |
socket.emit("sendMsg", JSON.stringify({ id: loggedUser.id, msg: msg })); | |
} | |
finally we render the connected users and an input to send messages.
return ( | |
<div> | |
<h3 className="d-flex justify-content-center"> Connected users : {user.usersList?.length} </h3> | |
<table className="table"> | |
<thead> | |
<tr> | |
<th> User name </th> | |
<th> Connection Date </th> | |
</tr> | |
</thead> | |
<tbody> | |
{user.usersList?.map(user => { | |
return (<tr key={user.id}> | |
<td> {user.userName} </td> | |
<td> {user.connectionTime} </td> | |
</tr>) | |
})} | |
</tbody> | |
</table> | |
<h3 className="d-flex justify-content-center"> User : {loggedUser?.userName} </h3> | |
<div style={{ borderStyle: "inset" }}> | |
<h2 className="d-flex justify-content-center"> Chat </h2> | |
{recMsg.listMsg?.map((msgInfo, index) => { return (<div className="d-flex justify-content-center" key={index}> <b>{msgInfo.userName} </b> : {msgInfo.msg} <small style={{ marginLeft: "18px", color: "blue", marginTop: "5px" }}> {msgInfo.time} </small> </div>) })} | |
</div> | |
<div className="d-flex justify-content-center"> | |
<Input style={{ width: "300px", display: "inline" }} id="inputmsg" onChange={(event) => setMsg(event.target.value)} /> | |
<Button className="btn btn-info" id="btnmsg" onClick={() => { sendMessage() }}> Send </Button> | |
</div> | |
</div > | |
); |
that's all for the front part, we move to the second one which is the server and the event management.
The server part
we create a simple node server.
the mission of the server is to respond to all the events which come from the clients.
We use an array to save the user information (a real database for serious things is more suitable)
We manage the connection and disconnection events by adding or removing the client from the clients array respectively.
When the server catch the SendMsg event, it broadcast it to all the logged client (we can create rooms if we want more control or just emit it to a specific client by passing his socket id)
const express = require("express"); | |
const http = require("http"); | |
const socketIo = require("socket.io"); | |
const port = process.env.PORT || 4001; | |
const index = require("./routes/index"); | |
const moment = require("moment"); | |
const app = express(); | |
app.use(index); | |
const server = http.createServer(app); | |
const io = socketIo(server); | |
let users = []; | |
io.on("connection", (socket) => { | |
socket.on("login", (userName) => { | |
users.push({ id: socket.id, userName: userName, connectionTime: new moment().format("YYYY-MM-DD HH:mm:ss") }); | |
socket.emit("connecteduser", JSON.stringify(users[users.length - 1])); | |
io.emit("users", JSON.stringify(users)); | |
}); | |
socket.on("sendMsg", msgTo => { | |
msgTo = JSON.parse(msgTo); | |
const minutes = new Date().getMinutes(); | |
io.emit("getMsg", | |
JSON.stringify({ | |
id: socket.id, | |
userName: users.find(e => e.id == msgTo.id).userName, | |
msg: msgTo.msg, | |
time: new Date().getHours() + ":" + (minutes < 10 ? "0" + minutes : minutes) | |
})); | |
}); | |
socket.once("disconnect", () => { | |
let index = -1; | |
if (users.length >= 0) { | |
index = users.findIndex(e => e.id == socket.id); | |
} | |
if (index >= 0) | |
users.splice(index, 1); | |
io.emit("users", JSON.stringify(users)); | |
}); | |
}); | |
server.listen(port, () => console.log(`Listening on port ${port}`)); |
The git repo :
KaidiMohammed
/
chatapp
a simple chat app made with next js, socket io
Getting Started
In the root folder there are two folders :D
The first folder : socket-io-server
It contains the io socket server. in order to run the server, run the commands bellow :
- npm install
- npm start
The second folder : NextChat
It contains the next js chat application. In order to run the application, run the commands bellow :
- npm install
- npm run dev
- Go to : http://localhost:9000 (by default)
Description
NextChat is a simple react-based chat application. Each client join the chat can send messages to the other members. The library Socket.IO is used for bi-directional communication between clients. Enjoy.
to see the final result, please click here : NextChat
Thanks for reading.
Top comments (3)
I dont see what do you mean by this, but I use pass express server as an argument to socketIO
Using NextJs this way is misusing it, better to use Create-React-App if you do not want to use NextJs server.
totally true, in this case next is not really useful !