Hi everyone in this post I will share with everyone my personal experience building a chat application in nextjs. To practice websockets integration.
Why are you building this app?
I have been having troubles implementing sockets on a nextjs base application, so I wanted to build an app that was really focus on the use of websockets, so for that reason and because it’s one of the most common examples when you want to learn to use sockets, a chat app was the perfect fit for this project.
What will be you using for the frontend?
For the frontend part I will be using the components from shadcn, alongside with tailwind, and that pretty much everything that I will use there.
Design of the app
When I started this project I thought that one thing that was need for this app, were users, however, how the time past and I develop the app I quite realize that the focus for this app need to be the sockets, so I will skip the users part an just focus on the socket integrations.
Socket integration
For the socket integration I use https://socket.io/ and follow their integration guide about nextjs ( https://socket.io/how-to/use-with-nextjs)
Overview of the socket io integration
On socket.io the way to integrate nextjs is to create a custom nextjs server, for that we need to create a server.js
file and in our package.json
call it how the entry point for the application,
just like these:
{
"scripts": {
+ "dev": "node server.js",
+ "start": "NODE_ENV=production node server.js"
}
}
I personal like to have a separete command on dev for test sockets so instead of using dev
I use dev:socket
Depending if we use app router or pages on our nextjs app, we will need to add some lines to the file socket.js
in the client part, we then use a useEffect
and start with the connection to the socket. But I will skip this to start talking about the changes that I did to the integration to work better with them.
My personal adaptations to the integration
First of all I create a provider
for sharing the instance of the socket into the app. So in a folder for all my providers, I write a socket.provider.tsx
file, that looks like these:
"use client"
import { socket } from "@/socket"
import { createContext, useContext, useEffect, useState } from "react"
export const SocketContext = createContext<typeof socket | null>(null)
export function SocketProvider({ children }: { children: React.ReactNode }) {
const [isConnected, setIsConnected] = useState(false)
const [transport, setTransport] = useState("N/A")
useEffect(() => {
if (socket.connected) {
onConnect()
}
function onConnect() {
setIsConnected(true)
setTransport(socket.io.engine.transport.name)
console.log(socket)
socket.io.engine.on("upgrade", (transport: any) => {
setTransport(transport.name)
})
}
function onDisconnect() {
setIsConnected(false)
setTransport("N/A")
}
socket.on("connect", onConnect)
socket.on("disconnect", onDisconnect)
return () => {
socket.off("connect", onConnect)
socket.off("disconnect", onDisconnect)
}
}, [])
return (
<SocketContext.Provider value={socket}>{children}</SocketContext.Provider>
)
}
export function useSocket(event?: string, callback?: (data: any) => void) {
const socket = useContext(SocketContext)
useEffect(() => {
if (event && callback && socket) {
socket?.on(event, callback)
}
return () => {
socket?.off(event, callback)
}
}, [callback, event, socket])
return socket
}
We create a context called SocketContext
inside the SocketProvider
we add the code that socket io shows for creating a socket connection and pass the instance of the socket to the value of the provider. Finally we have a hook
for adding a new event and a callback for that specific event.
In our app we will have something like these:
useSocket(ChatEvent.Send, data => {
setCurrentMessages([...getCurrentMessages(), { id: 0, msg: data, user: 1 }])
})
And in the server.js
file something like these:
io.on("connection", socket => {
socket.on(ChatEvent.Send, data => {
onSendChatEvent(socket, data)
})
})
Final words
I know that this post was more focus on sharing about the integration of socket on nextjs, but that also the reason that I started the project in first place, so I didn’t find a justification to share how the rest of the app was build, so yeah, that was pretty much everything that I wanted to talk about, in the future I will start integrating sockets for my applications.
Top comments (0)