101 lines
2.2 KiB
TypeScript
101 lines
2.2 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import socket from "@/lib/socket.io";
|
|
|
|
type RoomUpdatePayload<T> = {
|
|
roomId: string;
|
|
payloads: T[];
|
|
};
|
|
|
|
type RoomErrorPayload = {
|
|
roomId?: string;
|
|
message?: string;
|
|
};
|
|
|
|
type UpdateMode = "append" | "replace";
|
|
|
|
export function useSocketRoom<T>(
|
|
roomId: string,
|
|
getKey?: (item: T) => string | number,
|
|
updateMode: UpdateMode = "append",
|
|
) {
|
|
const [data, setData] = useState<T[]>([]);
|
|
const [info, setInfo] = useState(
|
|
"No data yet — join the room to start receiving",
|
|
);
|
|
|
|
const clearRoom = useCallback(
|
|
(id?: string | number) => {
|
|
if (id !== undefined && getKey) {
|
|
setData((prev) => prev.filter((item) => getKey(item) !== id));
|
|
setInfo(`Removed item ${id}`);
|
|
return;
|
|
}
|
|
console.log("cleared data from the room");
|
|
setData([]);
|
|
setInfo("Room data cleared");
|
|
},
|
|
[getKey],
|
|
);
|
|
|
|
useEffect(() => {
|
|
function handleConnect() {
|
|
socket.emit("join-room", roomId);
|
|
setInfo(`Joined room: ${roomId}`);
|
|
}
|
|
|
|
function handleUpdate(payload: RoomUpdatePayload<T>) {
|
|
// protects against other room updates hitting this hook
|
|
if (payload.roomId !== roomId) return;
|
|
|
|
// resetting room data for rooms that just need updated data.
|
|
if (updateMode === "replace") {
|
|
setData(payload.payloads);
|
|
} else {
|
|
setData((prev) => [...payload.payloads, ...prev]);
|
|
}
|
|
|
|
setInfo("");
|
|
}
|
|
|
|
function handleError(err: RoomErrorPayload) {
|
|
if (err.roomId && err.roomId !== roomId) return;
|
|
setInfo(err.message ?? "Room error");
|
|
}
|
|
|
|
socket.on("connect", handleConnect);
|
|
socket.on("room-update", handleUpdate);
|
|
socket.on("room-error", handleError);
|
|
|
|
if (!socket.connected && socket.disconnected) {
|
|
socket.connect();
|
|
}
|
|
|
|
// If already connected, join immediately
|
|
if (socket.connected) {
|
|
socket.emit("join-room", roomId);
|
|
setInfo(`Joined room: ${roomId}`);
|
|
}
|
|
|
|
return () => {
|
|
socket.emit("leave-room", roomId);
|
|
|
|
socket.off("connect", handleConnect);
|
|
socket.off("room-update", handleUpdate);
|
|
socket.off("room-error", handleError);
|
|
};
|
|
}, [roomId, updateMode]);
|
|
|
|
return { data, info, clearRoom };
|
|
}
|
|
|
|
/*
|
|
|
|
const isDockDoorPage = location.pathname.startsWith("/dockdoor");
|
|
|
|
useSocketRoom(
|
|
dockId ? `dockdoor:${dockId}` : null,
|
|
isDockDoorPage,
|
|
);
|
|
|
|
*/
|