Background
I'm trying to establish and connect a socket using Next.js. I'm following the standard guide that uses an API call to test if a socket server is already running and creates one if not.
I have an API script at pages/api/socket/io
that looks like this:
import { Server } from "socket.io";
export default function SocketHandler(req, res) {
if (res.socket.server.io) {
console.log("Already set up");
res.end();
return;
}
const io = new Server(res.socket.server);
// Event handler for client connections
io.on('connection', (socket) => {
const clientId = socket.id;
console.log('A client connected');
console.log(`A client connected. ID: ${clientId}`);
io.emit('client-new', clientId);
// Event handler for receiving messages from the client
socket.on('message', (data) => {
console.log('Received message:', data);
});
// Event handler for client disconnections
socket.on('disconnect', () => {
console.log('A client disconnected.');
});
});
res.socket.server.io = io;
res.end();
}
I have a page under pages/chat.js
that pings /api/socket/io
to make sure the socket server is running, then attempts to connect to it.
import React, { useEffect, useState } from "react";
import io from "socket.io-client";
let socket;
const Page = () => {
const [message, setMessage] = useState("");
const [username, setUsername] = useState("");
useEffect(() => {
socketInitializer();
return () => {
socket.disconnect();
};
}, []);
async function socketInitializer() {
// ping the server to setup a socket if not already running
await fetch("/api/socket/io");
// Setup the Socket
socket = io({ path: "/api/socket/ping" });
// Standard socket management
socket.on('connect', () => {
console.log('Connected to the server');
});
socket.on('disconnect', () => {
console.log('Disconnected from the server');
});
socket.on('connect_error', (error) => {
console.log('Connection error:', error);
});
socket.on('reconnect', (attemptNumber) => {
console.log('Reconnected to the server. Attempt:', attemptNumber);
});
socket.on('reconnect_error', (error) => {
console.log('Reconnection error:', error);
});
socket.on('reconnect_failed', () => {
console.log('Failed to reconnect to the server');
});
// Manage socket message events
socket.on('client-new', (message) => {
console.log("new client", message);
});
socket.on('message', (message) => {
console.log("Message", message);
});
socket.on('client-count', (count) => {
console.log("clientCount", count)
});
}
function handleSubmit(e) {
e.preventDefault();
socket.emit("message", {
username,
message
});
setMessage("");
}
return (
<div>
<h1>Chat app</h1>
<h1>Enter a username</h1>
<input value={username} onChange={(e) => setUsername(e.target.value)} />
<div>
<form onSubmit={handleSubmit}>
<input
name="message"
placeholder="enter your message"
value={message}
onChange={(e) => setMessage(e.target.value)}
autoComplete={"off"}
/>
</form>
</div>
</div>
);
};
export default Page;
/api/socket/ping
is a simple script that doesn't do much beyond return ok status. I'm assuming it should check that the server is running and hold any logic to check the client is still valid in the future, but it shouldn't be preventing the client from connecting at this point.
It looks like this:
export default async function handler(req, res) {
return res.status(200).send("OK");
}
Problem
The issue I'm having is that it seems the socket server is getting set up. However, I can't get the client to connect.
I'm getting an error that suggests I may need to provide some additional configuration options as part of the client setup socket = io({ path: "/api/socket/ping" });
, but I'm not sure where to start.
I'm running the server on localhost port 3000. This is the error I'm getting from :
Connection error: Error: server error
at Socket.onPacket (socket.js:318:1)
at Emitter.emit (index.mjs:136:1)
at Polling.onPacket (transport.js:97:1)
at callback (polling.js:115:1)
at Array.forEach (<anonymous>)
at Polling.onData (polling.js:118:22)
at Emitter.emit (index.mjs:136:1)
at Request.onLoad (polling.js:361:1)
at xhr.onreadystatechange (polling.js:297:1)
Request
Please explain why the client is not connecting and make recommendations to fix the issue.
import { Server } from "socket.io";
import cors from "cors";
import nextConnect from "next-connect";
const handler = nextConnect();
// Enable CORS
handler.use(cors());
handler.all((req, res) => {
if (res.socket.server.io) {
console.log("Already set up");
res.end();
return;
}
const io = new Server(res.socket.server);
// Event handler for client connections
io.on("connection", (socket) => {
const clientId = socket.id;
console.log("A client connected");
console.log(`A client connected. ID: ${clientId}`);
io.emit("client-new", clientId);
// Event handler for receiving messages from the client
socket.on("message", (data) => {
console.log("Received message:", data);
});
// Event handler for client disconnections
socket.on("disconnect", () => {
console.log("A client disconnected.");
});
});
res.socket.server.io = io;
res.end();
});
export default handler;