Hello Guys, Today in this post we will build a simple real-time views component in NEXT JS powered by Socket.IO and Node JS. Socket programming facilitates real-time communication between a server and clients. By the end, you’ll have a functional real-time view and a clear understanding of how Socket.IO and Next.js work together.
Make sure you have the following installed on your machine:
Create a new Node.js project and install the necessary packages, I will be using typescript.
mkdir realtime-view-server
cd realtime-view-server
npm init -y
npm install -D @types/node ts-node typescript
npm install express socket.io cors
Let’s code step by step:
Import Dependencies:
import { createServer } from 'http' import { Server } from 'socket.io'
Here, the code imports the necessary modules for creating an HTTP server (http
), and setting up a Socket.IO server (socket.io
).
2. Initialize Variables:
...
let count = 0
let httpServer = createServer()
const io = new Server(httpServer, {
cors: {origin: 'http://localhost:3000'} })
The variable count
is initialized to keep track of the number of connected clients. HTTP server is created using Node.js’s http
module. This server is then passed to the Server
constructor of Socket.IO, creating a WebSocket server (io
). The cors
configuration ensures that the server allows connections from http://localhost:3000
.
3. Handle Connection Events:
...
io.on('connection', (socket) => {
count++;
console.log("connected: ", count)
socket.on('disconnect', () => {
count--
console.log("disconnected: ", count)
socket.broadcast.emit("count", count)
})
socket.emit("count", count)
socket.broadcast.emit("count", count)
})
The io.on('connection', ...)
block listens for incoming socket connections. When a client connects ('connection'
event), the server increments the count
variable, emits the count to the client also broadcasts the count to other clients connected, and sets up event listeners for disconnection. On disconnection ('disconnect'
event), the server decrements the count, and broadcasts the count update to all connected clients except the disconnected one (socket.broadcast.emit
).
...
httpServer.listen(3001)
console.log("listening port 3001")
The HTTP server is configured to listen on port 3001.
Final code for the server
import { createServer } from 'http'
import { Server } from 'socket.io'
let count = 0
let httpServer = createServer()
const io = new Server(httpServer, {
cors: {
origin: 'http://localhost:3000'
}
})
io.on('connection', (socket) => {
count++;
console.log("connected: ", count)
socket.on('disconnect', () => {
count--
console.log("disconnected: ", count)
socket.emit("count", count)
socket.broadcast.emit("count", count)
})
socket.emit("count", count)
socket.broadcast.emit("count", count)
})
httpServer.listen(3001)
console.log("listening port 3001")
In the package.json configure a start command.
//package.json
{
"name": "realtime-view-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node index"
},
"author": "codewithmarish",
"license": "ISC",
"dependencies": {
"socket.io": "^4.7.2"
},
"devDependencies": {
"@types/node": "^20.10.0",
"ts-node": "^10.9.1",
"typescript": "^5.3.2"
}
}
Now you can start your server using npm start
from the command line.
Create a new Next.js app using below:
npx create-next-app@latest
Install the socket.io-client
package:
npm install socket.io-client
Now, create a RealtimeView component (components/RealtimeView.tsx
):
// /components/RealtimeView.tsx
"use client"
import React, { useEffect, useState } from 'react'
import io from 'socket.io-client'
const API_URL = 'http://localhost:3001/'
const socket = io(API_URL, { autoConnect: false })
const RealtimeView = () => {
const [views, setViews] = useState(0)
useEffect(() => {
socket.connect()
socket.on("count", (count) => {
setViews(count)
})
return () => {
socket.disconnect()
}
}, [])
return (
<div>
<h2 className='text-[100px] md:text-[200px] lg:text-[300px] flex items-center text-center font-extrabold'>
<span className="relative flex h-5 w-5 mr-4">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-5 w-5 bg-green-500"></span>
</span>
<span className='leading-[80px] md:leading-[150px] lg:leading-[220px]'>{views}<span className='block text-base md:text-2xl lg:text-4xl'>Online</span></span></h2>
</div >
)
}
export default RealtimeView
First let's import the necessary modules for building the component, and managing side effects in functional components (useEffect
and useState
), and establishing a client-side socket connection using socket.io-client
. The API_URL
variable holds the URL for the Socket.IO server. The socket
object is created using io
from, with the autoConnect
option set to false
as we will establish a connection manually. The RealtimeView
component component utilizes the state hook (useState
) to manage the views
state, representing the count of connected users. When the component mounts, it establishes a connection to the socket server (socket.connect()
) and listens for the "count" event. The count received from the server updates the component state (setViews(count)
). The useEffect
also includes a cleanup function (return () => { socket.disconnect(); }
) to disconnect the socket when the component is unmounted. The component’s render function returns JSX, displaying the current count (views
). I have used ping animation from the below Tailwind docs
Now, let’s use the RealtimeView
component in the app/pages.tsx
file:
// app/pages.tsx
import RealtimeView from '@/components/RealtimeView';
export default function Home() {
return (
<main className="min-h-screen flex justify-center items-center">
<RealtimeView/>
</main>
)
}
Now you can run the Next JS app using n
pm run dev
Visit http://localhost:3000
in your browser to see the Realtime View in action. You can open one in normal mode and another in incognito or a different browser. As users connect and disconnect, the view count updates in real time.
Congratulations! You’ve successfully created a Realtime View component using Socket.IO, Node.js, and Next.js. Feel free to explore and expand upon this foundation for more complex real-time features in your projects.